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

时间:2022-05-18 17:19:55

I have a class with some abstract methods, but I want to be able to edit a subclass of that class in the designer. However, the designer can't edit the subclass unless it can create an instance of the parent class. So my plan is to replace the abstract methods with stubs and mark them as virtual - but then if I make another subclass, I won't get a compile-time error if I forget to implement them.

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

Is there a way to mark the methods so that they have to be implemented by subclasses, without marking them as abstract?

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

7 个解决方案

#1


9  

Well you could do some really messy code involving #if - i.e. in DEBUG it is virtual (for the designer), but in RELEASE it is abstract. A real pain to maintain, though.

那么你可以做一些涉及#if的非常混乱的代码 - 即在DEBUG中它是虚拟的(对于设计者而言),但在RELEASE中它是抽象的。但是,维持真正的痛苦。

But other than that: basically, no. If you want designer support it can't be abstract, so you are left with "virtual" (presumably with the base method throwing a NotImplementedException).

但除此之外:基本上,没有。如果你想要设计师的支持它不能是抽象的,所以你留下了“虚拟”(大概是使用基本方法抛出一个NotImplementedException)。

Of course, your unit tests will check that the methods have been implemented, yes? ;-p

当然,你的单元测试会检查方法是否已经实现,是吗? ;-p

Actually, it would probably be quite easy to test via generics - i.e. have a generic test method of the form:

实际上,通过泛型测试可能很容易 - 即具有以下形式的通用测试方法:

[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
}

#2


5  

You could use the reference to implementation idiom in your class.

您可以在类中使用对实现习语的引用。

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 just exposes the interface you want but forwards all the calls to the implementation object. You extend the behavior by sub-classing ADesignerHappyImp, which forces you to implement all the abstract members.

DesignerHappy只显示您想要的接口,但将所有调用转发给实现对象。您可以通过对ADesignerHappyImp进行子类化来扩展行为,这会强制您实现所有抽象成员。

You can provide a default implementation of ADesignerHappyImp, which is used to initialize DesignerHappy by default and expose a property that allows you to change the implementation.

您可以提供ADesignerHappyImp的默认实现,默认情况下用于初始化DesignerHappy并公开允许您更改实现的属性。

#3


1  

Note that "DesignMode" is not set in the constructor. It's set after VS parses the InitializeComponents() method.

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

#4


0  

I know its not quite what you are after but you could make all of your stubs in the base class throw the NotImplementedException. Then if any of your subclasses have not overridden them you would get a runtime exception when the method in the base class gets called.

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

#5


0  

The Component class contains a boolean property called "DesignMode" which is very handy when you want your code to behave differently in the designer than at runtime. May be of some use in this case.

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

#6


0  

As a general rule, if there's no way in a language to do something that generally means that there's a good conceptual reason not to do it.

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

Sometimes this will be the fault of the language designers - but not often. Usually I find they know more about language design than I do ;-)

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

In this case you want a un-overridden virtual method to throw a compile time exception (rather and a run time one). Basically an abstract method then.

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

Making virtual methods behave like abstract ones is just going to create a world of confusion for you further down the line.

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

On the other hand, VS plug in design is often not quite at the same level (that's a little unfair, but certainly less rigour is applied than is at the language design stage - and rightly so). Some VS tools, like the class designer and current WPF editors, are nice ideas but not really complete - yet.

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

In the case that you're describing I think you have an argument not to use the class designer, not an argument to hack your code.

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

At some point (maybe in the next VS) they'll tidy up how the class designer deals with abstract classes, and then you'll have a hack with no idea why it was coded that way.

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

It should always be the last resort to hack your code to fit the designer, and when you do try to keep hacks minimal. I find that it's usually better to have concise, readable code that makes sense quickly over Byzantine code that works in the current broken tools.

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

#7


0  

To use ms as an example...

以ms为例......

Microsoft does this with the user control templates in silverlight. #if is perfectly acceptable and it is doubtful the the tooling will work around it anytime soon. IMHO

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

#1


9  

Well you could do some really messy code involving #if - i.e. in DEBUG it is virtual (for the designer), but in RELEASE it is abstract. A real pain to maintain, though.

那么你可以做一些涉及#if的非常混乱的代码 - 即在DEBUG中它是虚拟的(对于设计者而言),但在RELEASE中它是抽象的。但是,维持真正的痛苦。

But other than that: basically, no. If you want designer support it can't be abstract, so you are left with "virtual" (presumably with the base method throwing a NotImplementedException).

但除此之外:基本上,没有。如果你想要设计师的支持它不能是抽象的,所以你留下了“虚拟”(大概是使用基本方法抛出一个NotImplementedException)。

Of course, your unit tests will check that the methods have been implemented, yes? ;-p

当然,你的单元测试会检查方法是否已经实现,是吗? ;-p

Actually, it would probably be quite easy to test via generics - i.e. have a generic test method of the form:

实际上,通过泛型测试可能很容易 - 即具有以下形式的通用测试方法:

[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
}

#2


5  

You could use the reference to implementation idiom in your class.

您可以在类中使用对实现习语的引用。

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 just exposes the interface you want but forwards all the calls to the implementation object. You extend the behavior by sub-classing ADesignerHappyImp, which forces you to implement all the abstract members.

DesignerHappy只显示您想要的接口,但将所有调用转发给实现对象。您可以通过对ADesignerHappyImp进行子类化来扩展行为,这会强制您实现所有抽象成员。

You can provide a default implementation of ADesignerHappyImp, which is used to initialize DesignerHappy by default and expose a property that allows you to change the implementation.

您可以提供ADesignerHappyImp的默认实现,默认情况下用于初始化DesignerHappy并公开允许您更改实现的属性。

#3


1  

Note that "DesignMode" is not set in the constructor. It's set after VS parses the InitializeComponents() method.

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

#4


0  

I know its not quite what you are after but you could make all of your stubs in the base class throw the NotImplementedException. Then if any of your subclasses have not overridden them you would get a runtime exception when the method in the base class gets called.

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

#5


0  

The Component class contains a boolean property called "DesignMode" which is very handy when you want your code to behave differently in the designer than at runtime. May be of some use in this case.

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

#6


0  

As a general rule, if there's no way in a language to do something that generally means that there's a good conceptual reason not to do it.

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

Sometimes this will be the fault of the language designers - but not often. Usually I find they know more about language design than I do ;-)

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

In this case you want a un-overridden virtual method to throw a compile time exception (rather and a run time one). Basically an abstract method then.

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

Making virtual methods behave like abstract ones is just going to create a world of confusion for you further down the line.

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

On the other hand, VS plug in design is often not quite at the same level (that's a little unfair, but certainly less rigour is applied than is at the language design stage - and rightly so). Some VS tools, like the class designer and current WPF editors, are nice ideas but not really complete - yet.

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

In the case that you're describing I think you have an argument not to use the class designer, not an argument to hack your code.

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

At some point (maybe in the next VS) they'll tidy up how the class designer deals with abstract classes, and then you'll have a hack with no idea why it was coded that way.

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

It should always be the last resort to hack your code to fit the designer, and when you do try to keep hacks minimal. I find that it's usually better to have concise, readable code that makes sense quickly over Byzantine code that works in the current broken tools.

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

#7


0  

To use ms as an example...

以ms为例......

Microsoft does this with the user control templates in silverlight. #if is perfectly acceptable and it is doubtful the the tooling will work around it anytime soon. IMHO

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