Могу ли я заставить подклассы переопределять метод, не делая его абстрактным?

StackOverflow https://stackoverflow.com/questions/239408

Вопрос

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

Есть ли способ пометить методы так, чтобы они были реализованы подклассами, не помечая их как абстрактные?

Это было полезно?

Решение

Ну, вы могли бы сделать какой-то действительно грязный код, включающий #if - то есть в DEBUG он виртуален (для дизайнера), но в RELEASE это абстрактно. Хотя настоящую боль поддерживать.

Но кроме этого: в основном нет. Если вам нужна поддержка дизайнера, она не может быть абстрактной, поэтому у вас остается «виртуальный». (предположительно с базовым методом, генерирующим NotImplementedException ).

Конечно, ваши юнит-тесты проверит, что методы были реализованы, да? ;-p

На самом деле, вероятно, было бы довольно легко протестировать с помощью дженериков - то есть иметь общий метод тестирования в форме:

[Test]
public void TestFoo() {
  ActualTest<Foo>();
}
[Test]
public void TestBar() {
  ActualTest<Bar>();
}

static void ActualTest<T>() where T : SomeBaseClass, new() {
  T obj = new T();
  Assert.blah something involving obj
}

Другие советы

Вы можете использовать ссылку на идиому реализации в своем классе.

public class DesignerHappy
{
    private ADesignerHappyImp imp_;

    public int MyMethod()
    {
        return imp_.MyMethod()    
    }

    public int MyProperty
    {
        get { return imp_.MyProperty; }
        set { imp_.MyProperty = value; }
    }
}

public abstract class ADesignerHappyImp
{
    public abstract int MyMethod();
    public int MyProperty {get; set;}
}

DesignerHappy просто предоставляет нужный интерфейс, но перенаправляет все вызовы к объекту реализации. Вы расширяете поведение с помощью подкласса ADesignerHappyImp, что заставляет вас реализовывать все абстрактные члены.

Вы можете предоставить реализацию ADesignerHappyImp по умолчанию, которая используется для инициализации DesignerHappy по умолчанию и предоставления свойства, позволяющего изменить реализацию.

Обратите внимание, что " DesignMode " не установлен в конструкторе. Это устанавливается после того, как VS анализирует метод InitializeComponents ().

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

Класс Component содержит логическое свойство с именем " DesignMode " что очень удобно, когда вы хотите, чтобы ваш код вел себя в конструкторе иначе, чем во время выполнения. Может быть полезно в этом случае.

Как правило, если в языке нет способа сделать что-либо, это обычно означает, что есть веская концептуальная причина не делать этого.

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

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

Заставить виртуальные методы вести себя как абстрактные просто создаст для вас мир путаницы в дальнейшем.

С другой стороны, дизайн подключаемого модуля VS часто не совсем на том же уровне (это немного несправедливо, но, конечно, применяется меньше строгости, чем на этапе проектирования языка - и это правильно). Некоторые инструменты VS, такие как конструктор классов и текущие редакторы WPF, являются хорошими идеями, но не полностью завершены - пока.

В случае, когда вы описываете, я думаю, у вас есть аргумент не использовать конструктор классов, а не аргумент для взлома вашего кода.

В какой-то момент (возможно, в следующем VS) они приведут в порядок, как конструктор классов работает с абстрактными классами, и тогда у вас будет хак, не зная, почему он был так закодирован.

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

Использовать ms в качестве примера ...

Microsoft делает это с помощью пользовательских шаблонов управления в Silverlight. #if вполне приемлемо и сомнительно, что инструмент обойдет его в ближайшее время. ИМХО

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top