Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interface with implementation without abstract class?

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?

like image 234
Jake Avatar asked Jan 17 '23 21:01

Jake


1 Answers

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).

like image 83
Matten Avatar answered Jan 31 '23 05:01

Matten