Разрешить реализацию интерфейса только для определенных классов - PullRequest
14 голосов
/ 24 апреля 2011

Можно ли разрешить только некоторые конкретные классы для реализации интерфейса? Допустим, я создал интерфейс IMyInterface и хочу, чтобы только классы, производные от UserControl, имели возможность реализовать мой интерфейс. Это возможно?

Ответы [ 6 ]

10 голосов
/ 24 апреля 2011

Вы не можете, но вы можете достичь чего-то похожего, добавив свойство Control в ваш интерфейс и по соглашению заставляя все реализации возвращать this. Не решает вашу проблему, но заставляет разработчика задуматься о том, действительно ли интерфейс принадлежит ему. Также позволяет пользователю интерфейса извлекать элемент управления безопасным для типов способом без приведения.

interface IMyInterface
{
    void Foo();
    UserControl Control { get; }
}


class MyControl : UserControl, IMyInterface
{
    public void Foo()
    {
        // TODO: Write code here
    }

    UserControl IMyInterface.Control
    {
        get { return this; }
    }
}

UPDATE

Есть и другое решение - создание универсального метода. Сам интерфейс не будет ограничен, но будет работать метод. Например, следующий метод требует, чтобы его параметр наследовал UserControl и реализовывал IMyInterface:

void Bar<T>(T item)
  where T : UserControl, IMyInterface
{
    item.Width = 120;    // user control property
    item.Foo();          // IMyInterface method
}
6 голосов
/ 27 мая 2017

Я понимаю, что это старый пост, но мне пришлось решить именно эту проблему.

Вот как вы можете это сделать:

class BaseClass { }

interface OnlyBaseClass<TSelf> where TSelf : BaseClass, OnlyBaseClass<TSelf>
{

}

class ChildClass : BaseClass, OnlyBaseClass<ChildClass> { }

class ImpostorClass : OnlyBaseClass<ImposterClass> { }

interface ImposterInterface : OnlyBaseClass<ImposterInterface > { }

Попробуйте скомпилировать выше. Вы заметите, что он не компилируется (из-за двух самозванцев, одного класса, одного интерфейса).

Ограничение на TSelf можно понимать как:

TSelf должен: наследовать от BaseClass и реализовать OnlyBaseClass <<em> TSelf >

... что может сделать только тип, унаследованный от BaseClass и реализующий OnlyBaseClass .

Вы можете быть умным и делать следующее:

class AdvancedImpostorClass : OnlyBaseClass<ChildClass> {}

... который будет компилироваться. Вы можете предотвратить попадание этих типов самозванцев в ваш код, используя те же ограничения в любых методах, которые принимают их в качестве аргументов, например, так:

public SomeMethod<TBaseAndInterface>(TBaseAndInterface value)
    where TBaseAndInterface: BaseClass, OnlyBaseClass<TBaseAndInterface>
{ }

Все это стало возможным благодаря силе F-связанного полиморфизма .

3 голосов
/ 24 апреля 2011

Звучит так, будто вы хотите что-то вроде этого:

abstract class IMyInterface : UserControl { }

Конечно, IMyInterface больше не является подходящим именем, но любой класс, производный от IMyInterface, также будет производным от UserControl, что бы удовлетворить ваши требования.

2 голосов
/ 24 апреля 2011

Нет, нет способа ограничить реализацию интерфейса конкретными типами. Зачем тебе это нужно? Почему потребитель абстракции заботится о конкретных типах, которые реализуют этот контракт? Каков ваш вариант использования?

2 голосов
/ 24 апреля 2011

Это невозможно. Если вы видите интерфейс, вы можете реализовать его.

1 голос
/ 24 апреля 2011

Случай, который вы описываете, кажется, соответствует "абстрактному методу в вашем родительском классе" (здесь userControl), если интерфейс уже не существует для других целей.

Без основного тела, производные классы должны будут предоставлятьповедение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...