我可以强制子类覆盖方法而不使其抽象化吗?

时间:2008-10-27 09:28:08

标签: c# .net visual-studio-2008 abstract-class

我有一个带有一些抽象方法的类,但我希望能够在设计器中编辑该类的子类。但是,设计者无法编辑子类,除非它可以创建父类的实例。所以我的计划是用存根替换抽象方法并将它们标记为虚拟 - 但是如果我创建另一个子类,如果我忘记实现它们,我将不会遇到编译时错误。

有没有办法标记方法,以便它们必须由子类实现,而不将它们标记为抽象?

7 个答案:

答案 0 :(得分:9)

你可以做一些涉及#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
}

答案 1 :(得分: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并公开允许您更改实现的属性。

答案 2 :(得分:1)

请注意,构造函数中未设置“DesignMode”。在VS解析InitializeComponents()方法之后设置它。

答案 3 :(得分:0)

我知道它不是你想要的,但你可以让基类中的所有存根都抛出NotImplementedException。然后,如果您的任何子类没有覆盖它们,那么当调用基类中的方法时,您将获得运行时异常。

答案 4 :(得分:0)

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

答案 5 :(得分:0)

作为一般规则,如果语言中没有办法做某事通常意味着有一个很好的概念理由不这样做。

有时这将是语言设计者的错 - 但不常见。通常我发现他们比我更了解语言设计; - )

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

让虚拟方法像抽象方法一样,只会为你的下线创造一个混乱的世界。

另一方面,VS插件设计通常不是同一级别(这有点不公平,但肯定不如语言设计阶段那么严格 - 正确如此)。一些VS工具,比如类设计师和当前的WPF编辑器,都是很好的想法,但还不是很完整。

在你描述的情况下,我认为你有一个不使用类设计师的论点,而不是破解你的代码的论据。

在某些时候(可能在下一个VS中),他们会整理班级设计师处理抽象类的方式,然后你就会知道为什么会以这种方式进行编码。

它应该始终是破解你的代码以适应设计师的最后手段,并且当你试图保持最小的黑客时。我发现通常更好的是拥有简洁易读的代码,这些代码可以在当前破坏的工具中运行的拜占庭代码中快速理解。

答案 6 :(得分:0)

以ms为例......

Microsoft使用silverlight中的用户控件模板执行此操作。 #if是完全可以接受的,并且工具很快就能解决它是值得怀疑的。恕我直言