我能否强制子类重写一个方法而不将其声明为抽象的?

10

我有一个带有一些抽象方法的类,但是我想要能够在设计器中编辑该类的子类。然而,设计器无法编辑子类,除非它可以创建父类的实例。所以我的计划是用桩代码替换抽象方法,并将其标记为虚拟的 - 但是如果我创建另一个子类,如果我忘记实现这些方法,我将不会得到编译时错误。

是否有一种方法可以标记这些方法必须由子类实现,而不将它们标记为抽象的?


你是如何在设计师中设计基类的? - Lasse V. Karlsen
7个回答

9

你可以使用一些相当混乱的代码,涉及到#if——即在DEBUG中它是虚拟的(对于设计师来说),但在RELEASE中它是抽象的。不过这样做会很难维护。

除此之外,基本上没有其他方法。如果你想要设计师支持,它就不能是抽象的,因此只能使用"virtual"(可能需要让基础方法抛出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
}

5
你可以在你的类中使用实现引用惯用语法。
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
请注意,在构造函数中未设置“DesignMode”。它在VS解析InitializeComponents()方法之后设置。

0

我知道这并不是你想要的,但你可以在基类中创建所有stub并让它们抛出NotImplementedException。这样,如果任何子类没有重写这些方法,在基类中调用该方法时就会抛出运行时异常。


0

Component类包含一个名为“DesignMode”的布尔属性,当您希望在设计时与运行时中使代码的行为不同时,它非常方便。 在这种情况下可能会有所帮助。


0

通常情况下,如果一种语言无法做某件事情,那通常意味着有很好的概念性原因不去做它。

有时这可能是语言设计者的问题 - 但并不经常。通常我发现他们对语言设计的了解比我更多 ;-)

在这种情况下,您需要一个未被覆盖的虚拟方法来抛出编译时异常(而不是运行时异常)。基本上是一个抽象方法。

让虚拟方法像抽象方法一样行为只会在以后给您带来困惑。

另一方面,VS插件设计通常没有达到相同的水平(这有点不公平,但肯定比语言设计阶段应用的严格程度要低)。一些VS工具,如类设计器和当前的WPF编辑器,是不错的想法,但并不完整 - 至少目前还不完整。

在您所描述的情况下,我认为您有理由不使用类设计器,而不是亲自修改代码。

在某个时候(也许在下一个VS中),他们将整理类设计器如何处理抽象类,然后您将拥有一个没有任何理由编写的代码。

将代码修改以适应设计师应该始终是最后的选择,而且当你尝试这样做时,要尽量减少修改。我发现通常最好拥有简洁易读的代码,能够快速理解,而不是使用复杂难懂的代码来适应当前不完善的工具。


这一直是 Visual Studio 的一个缺陷,但你不能为了缺失多年的某些功能而牺牲可读性和可维护性。你有没有尝试过以编程方式修改复杂的 WinForms 程序?这需要更长的时间,并且很容易引起很多挫败感。微软加入了设计器是有原因的,我认为为了提高项目的可维护性进行一些“黑客”是完全合理的,只要确保记录下你正在做什么以及为什么这样做。 - Tim
@Tim - 我并不是说这种方法不合法,我的观点是应该把修改代码以适应工具作为最后的手段。在这种情况下,我认为最好的解决方案实际上是接受的答案 - 在虚拟成员中抛出 NotImplementedException 并对代码进行单元测试。 - Keith

0

以微软公司为例...

在Silverlight中,微软公司使用用户控件模板。 #if是完全可以接受的,而且工具很可能不会很快适应它。 依我之见。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接