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

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

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

Ответы [ 7 ]

9 голосов
/ 27 октября 2008

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

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

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

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

[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
}
5 голосов
/ 27 октября 2008

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

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 по умолчанию и предоставления свойства, позволяющего изменить реализацию.

1 голос
/ 20 ноября 2008

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

0 голосов
/ 19 октября 2011

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

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

0 голосов
/ 27 октября 2008

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

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

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

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

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

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

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

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

0 голосов
/ 27 октября 2008

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

0 голосов
/ 27 октября 2008

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

...