Reputation: 11430
I am writing a library and I want to have an interface
public interface ISkeleton
{
IEnumerable<IBone> Bones { get; }
void Attach(IBone bone);
void Detach(IBone bone);
}
The Attach() and Detach() implementation actually should be the same for every ISkeleton. Thus, it could essentially be:
public abstract class Skeleton
{
public IEnumerable<IBone> Bones { get { return _mBones; } }
public List<IBone> _mBones = new List<IBone>();
public void Attach(IBone bone)
{
bone.Transformation.ToLocal(this);
_mBones.add();
}
public void Detach(IBone bone)
{
bone.Transformation.ToWorld(this);
_mBones.Remove(bone);
}
}
But C# doesn't allow multiple inheritance. So among various issues, users have to remember to inherit from Skeleton every time they want to implement Skeleton.
I could use extension methods
public static class Skeleton
{
public static void Attach(this ISkeleton skeleton, IBone bone)
{
bone.Transformation.ToLocal(skeleton);
skeleton.Bones.add(bone);
}
public static void Detach(this ISkeleton skeleton, IBone bone)
{
bone.Transformation.ToWorld(this);
skeleton.Bones.Remove(bone);
}
}
But then I need to have
public interface ISkeleton
{
ICollection<IBone> Bones { get; }
}
Which I do not want, because it is not covariant and users can bypass the Attach() and Detach() methods.
Question: Must I really use an abstract Skeleton class or are there any or tricks and methods?
Upvotes: 4
Views: 367
Reputation: 133
You can create a wrapper class which implements the 'Attach' and 'Detach' methods and inject this Functionality to your Interface.
Upvotes: 0
Reputation: 21251
If you want to wrap ISkeleton
behaviour, you could always make it a composite object instead of inheriting the behaviour:
public class Body : ISkeleton
{
private SkeletonImpl _skeleton = new SkeletonImpl;
public IEnumerable<IBone> Bones { get { return _skeleton.Bones; } }
public void Attach(IBone bone)
{
_skeleton.Attach(bone);
}
public void Detach(IBone bone)
{
_skeleton.Detach(bone);
}
}
Upvotes: 1
Reputation: 1419
May be you just have to use sealed methods on abstract Skeleton class? This way they can't be overriden.
http://msdn.microsoft.com/en-us/library/aa645769(v=vs.71).aspx
Upvotes: 0
Reputation: 190943
I would make bones a special type that implements IEnumerable<T>
. That way it doesn't violate the single responsibility principle.
public interface ISkeleton
{
AttachableEnumerable<IBone> Bones { get; }
}
public class AttachableEnumerable<T> : IEnumerable<T>
{
// implementation needed.
void Attach(T item);
void Detach(T item);
}
Upvotes: 3
Reputation: 17631
If you need to expose the Attach
and Detach
methods in your interface, there is always a way to bypass your intended implementations, as all objects implementing the interface can implement them on their own style.
You can let the abstract class Skeleton
implement ISkeleton
and all classes which are Skeletons do inherit from Skeleton
, thus they implement ISkeleton
as well.
public interface ISkeleton { ... }
public abstract class Skeleton : ISkeleton { ... } // implement attach and detach
public class SampleSkeleton : Skeleton { ... }
This way you can use your SampleSkeleton
as ISkeleton
, you don't have to implement these functions as long as you inherit from Skeleton
and marking the methods as sealed
does not allow overriding them (as long as they are instance methods).
On a side node: Do name your abstract class with Base
at the end or mark the base class somehow else (but this is surely up to you).
Upvotes: 5