Mario Stoilov
Mario Stoilov

Reputation: 3447

Can you attach an interface to a defined class

Here is the situation. In some cases I find myself wanting a class, let's call it class C that has the same functionalities as class A, but with the addition that it has interface B implemented. For now I do it like this:

class C : A,B
{
   //code that implements interface B, and nothing else
}

The problem will come if class A happens to be sealed. Is there a way I can make class A implement interface B without having to define class C (with extension methods or something)

Upvotes: 12

Views: 912

Answers (4)

Mike Perrenoud
Mike Perrenoud

Reputation: 67898

Is there a way I can make class A implement interface B without having to define class C (with extension methods or something)

The short answer is no. You can't make A implement B because you don't have control of A. However, I think you're headed down the right road with extension methods. Consider this:

public static class AImplementsBExtensions
{
    public static void Func1(this A o) { }
    public static void Func2(this A o) { }
}

Now clearly I have no idea what methods exist on B, but this is how you can implement B on A when you can't inherit from it.

Bear in mind, this is not an implementation. If you add or remove methods from the interface you'll have to do that by hand here. But now you can do this:

var a = new A();
a.Func1();

Upvotes: 2

Knaģis
Knaģis

Reputation: 21485

You could try creating your class without the inheritance: class C : B and as a wrapper around A.

Additionally you can provide implicit conversion operators so that code like A obj = new C(new A()) would work similar to how a derived class would work.

class C : B
{
    private A _inner;
    public C(A inner)
    {
        this._inner = inner;
    }

    public A Inner { get { return this._inner; } }

    public static implicit operator A(C obj)
    {
        return obj == null ? (A)null : obj._inner;
    }

    public static implicit operator C(A obj)
    {
        return new C(obj);
    }
}

Upvotes: 0

Marc Gravell
Marc Gravell

Reputation: 1062855

Basically: no. That is part of what "mixins" could bring to the table, but the C# languauge doesn't currently support that (it has been discussed a few times, IIRC).

You will have to use your current approach, or (more commonly) just a pass-through decorator that encapsulates A rather than inheriting A.

class C : IB
{
    private readonly A a;
    public C(A a) {
        if(a == null) throw new ArgumentNullException("a");
        this.a = a;
    }

    // methods of IB:
    public int Foo() { return a.SomeMethod(); }
    void IB.Bar() { a.SomeOtherMethod(); }
}

Upvotes: 8

BartoszKP
BartoszKP

Reputation: 35891

The only way I see, is to change inheritance to aggregation, like this:

class C : B
{
    public C(A instanceToWrap)
    {
        this.innerA = instanceToWrap;
    }

    //coda that implements B

    private A innerA;
}

There seems to be a possibility to inject interface in run-time, as it is done with Array class and IEnumerable<T> interface, but it seems a bit of an overkill.

Upvotes: 3

Related Questions