Можете ли вы подключить интерфейс к определенному классу
Вот ситуация. В некоторых случаях я нахожу себя в классе, пусть называет его class C
, который имеет те же функции, что и class A
, но с добавлением, что он имеет interface B
. Пока я делаю это так:
class C : A,B
{
//code that implements interface B, and nothing else
}
Проблема придет, если class A
окажется запечатанным. Есть ли способ сделать class A
реализовать interface B
без необходимости определять class C
(с помощью методов расширения или что-то еще)
Ответы
Ответ 1
В принципе: нет. Это часть того, что "mixins" может привести к таблице, но С# languauge в настоящее время не поддерживает это (это обсуждалось несколько раз, IIRC).
Вам нужно будет использовать ваш текущий подход или (чаще всего) только сквозной декоратор, который инкапсулирует A
, а не наследует 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(); }
}
Ответ 2
Единственный способ, который я вижу, - изменить наследование на агрегацию, например:
class C : B
{
public C(A instanceToWrap)
{
this.innerA = instanceToWrap;
}
//coda that implements B
private A innerA;
}
Кажется, есть возможность внедрить интерфейс во время выполнения, как это делается с помощью Array
class и IEnumerable<T>
interface, но это кажется немного излишним.
Ответ 3
Есть ли способ сделать класс A реализовать интерфейс B без необходимости определять класс C (с помощью методов расширения или что-то еще)
Короткий ответ - нет. Вы не можете сделать A
реализовать B
, потому что у вас нет элемента управления A
. Тем не менее, я думаю, что вы направились по правильной дороге с помощью методов расширения. Рассмотрим это:
public static class AImplementsBExtensions
{
public static void Func1(this A o) { }
public static void Func2(this A o) { }
}
Теперь я не знаю, какие существуют методы на B
, но вы можете реализовать B
на A
, если вы не можете наследовать его.
Помните, что это не реализация.. Если вы добавите или удалите методы из интерфейса, вам придется сделать это вручную. Но теперь вы можете сделать это:
var a = new A();
a.Func1();
Ответ 4
Вы можете попробовать создать свой класс без наследования: class C : B
и как обертка вокруг A
.
Кроме того, вы можете предоставить неявные операторы преобразования, чтобы код типа A obj = new C(new A())
работал аналогично тому, как будет работать производный класс.
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);
}
}