внутренние абстрактные методы. Зачем кому-то их? - PullRequest
14 голосов
/ 20 февраля 2010

Сегодня я делал обзор кода и наткнулся на старый код, написанный каким-то разработчиком. Это выглядит примерно так

public abstract class BaseControl
{
    internal abstract void DoSomething();
}

Если у вас есть производный класс в той же сборке, он будет работать

public class DerivedControl : BaseControl
{
    internal override void DoSomething()
    {
    }
}

Но получение базового класса в другой сборке может привести к ошибке времени компиляции

DerivedControl does not implement inherited abstract member 'BaseControl.DoSomething()

Это заставило меня задуматься. Зачем кому-то объявлять метод как внутренний абстрактный?

Ответы [ 4 ]

12 голосов
/ 21 февраля 2010

Первоначальный программист хотел сделать производный элемент управления доступным для клиентского кода. Но не позволяйте клиенту наследовать и связываться с виртуальным методом. Это неплохая идея, обычно легко сломать базовый класс, переопределив метод и выполнив что-то вроде забвения вызова метода базового класса.

6 голосов
/ 20 февраля 2010

Один очевидный случай - когда метод получает или возвращает внутренний тип.Например, основные методы классов WPF Transform обрабатывают некоторые внутренние типы взаимодействия, которые WPF не предоставляет в качестве части своего открытого API.Поскольку подпись включает внутренние типы, метод не может быть открытым или защищенным.И все же ясно (уместно!), Чтобы различные классы Transform работали полиморфно.Поэтому базовые методы в Transform / GeneralTransform должны быть внутренними.

Другая, но связанная с этим причина - предотвращение внешнего деривации.В конце концов, архитекторы WPF могли бы раскрыть «безопасную» версию внутренних типов взаимодействия в защищенном абстрактном методе, чтобы пользователи могли создавать свои собственные классы Transform.Они этого не сделали, потому что не хотели справляться с тем, как люди могут использовать эту возможность, например, создавать неаффинные преобразования.Разрешение внешнего деривации сделало бы работу других классов в WPF намного более сложной, поэтому архитекторы решили разрешить только «одобренные» производные классы, сделав абстрактный метод внутренним.

1 голос
/ 20 февраля 2010

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

Полагаю, этот метод предотвращает внешнее наследование при сохранении видимости.

0 голосов
/ 22 февраля 2010

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

Теперь, если вы распространяете его dll, это позволит избежать клиентанаследовать и путать реализацию.

...