简体   繁体   English

为什么要使用空的抽象类而不是接口?

[英]Why to use an empty abstract class instead of an interface?

I use GWT and the Place & Activity mechanism. 我使用GWT和Place&Activity机制。

It's really sad that Place is a class because my custom place can't extend another class. Place是一个类真的很难过,因为我的自定义位置不能扩展另一个类。

When I look at the Place code, I see the following : 当我查看Place代码时,我看到以下内容:

public abstract class Place {

  /**
   * The null place.
   */
  public static final Place NOWHERE = new Place() {
  };

}

Seeing that, the Place can be an interface. 看到这个,Place可以是一个界面。 Is there a good reason that GWT team has chosen to make Place an abstract class instead of an interface ? 有没有一个很好的理由让GWT团队选择将Place放置为抽象类而不是接口?

And to generalize : is there a good reason to create really empty abstract class vs interface ? 并概括:是否有充分的理由创建真正空的抽象类vs接口?

In general I would not define an empty abstract class 一般来说,我不会定义一个空的抽象类

However, when I would expect some members in the future, I may decide to use abstract class instead of interface 但是,当我希望将来有些成员时,我可能决定使用抽象类而不是接口

"class" means: this IS A “阶级”是指:这是一个

"interface" means: this SUPPORTS “界面”的意思是:这个支持

For "Place" I could really see both with a little intuitive preference for class 对于“地方”,我真的可以看到两者都有一点点直观的偏好

Is there a good reason that GWT team has chosen to make Place an abstract class instead of an interface ? 有没有一个很好的理由让GWT团队选择将Place放置为抽象类而不是接口?

I can't think of one. 我想不出一个。 But to be realistic, complaining about it on SO is not going to achieve anything. 但实际上,在SO上抱怨它并不会有任何成就。

And to generalize : is there a good reason to create really empty abstract class vs interface ? 并概括:是否有充分的理由创建真正空的抽象类vs接口?

Hypothetically, you might do this to ensure that there is a single common base class for future anticipated requirements ... or for some other reason. 假设您可以这样做以确保存在单个公共基类以用于未来预期的需求......或者出于某种其他原因。

But generally speaking it is a bad idea ... IMO. 但总的来说这是一个坏主意...... IMO。

(Of course, things like this often happen for historical reasons; eg the abstract class may have had more members in the past that have since been removed.) (当然,这样的事情经常因历史原因而发生;例如, abstract类过去可能有更多的成员被删除了。)

I can't really tell for the Place (though I have a few ideas, see below), but it was discussed for the Activity : https://groups.google.com/d/topic/google-web-toolkit-contributors/V8rhZHiXFRk/discussion 我无法真正说出这个Place (虽然我有一些想法,见下文),但是对于Activity进行了讨论: https//groups.google.com/d/topic/google-web-toolkit-contributors / V8rhZHiXFRk /讨论

As far as we could go in history, Place has always been an abstract class in GWT (and FWIW, the NOWHERE place was added long after ; note that this commit references a Wave –soon to disappear from the internet– where we can see interface Place so it was an interface at some point in time while they designed the API). 就历史而言, Place 一直是 GWT中的一个抽象类(而FWIW, NOWHERE地方很久就被添加了;注意这个提交引用了一个Wave -soon从互联网上消失 - 我们可以看到interface Place所以它是在某个时间点的接口,而他们设计的API)。

Given that the PlaceHistoryGenerator (used when you GWT.create() a PlaceHistoryMapper ) looks at the places hierarchy, having an abstract class cuts down a whole lot of edge cases! 鉴于PlaceHistoryGenerator (当您使用PlaceHistoryGeneratorGWT.create() PlaceHistoryMapper )查看位置层次结构,具有抽象类会减少大量边缘情况!
Imagine your PlaceHistoryMapper references a PlaceTokenizers<Foo> and PlaceTokenizer<Bar> and you have a class FooBar implements Foo, Bar { } , which tokenizer should be used? 想象一下你的PlaceHistoryMapper引用了PlaceTokenizers<Foo>PlaceTokenizer<Bar> ,你有一个class FooBar implements Foo, Bar { } ,应该使用哪个tokenizer? If you don't reference the FooBar class explicitly in your PlaceHistoryMapper , the generator won't see it (or rather won't look at it), so which kind of code should it generate? 如果不引用FooBar类直接在您的PlaceHistoryMapper ,发电机不会看到它(或者更确切地说,不会看的话),所以这类型的代码应该是产生? And keep in mind that we all want determinism, so the generated code should always be the same. 请记住,我们都需要确定性,因此生成的代码应该始终相同。 Using a class, the generator can order them by their inheritance tree (from the most specific –most derived– to the least specific), and can safely assume that 2 places whose classes have no particular inheritance relationship are totally distinct, so they can be checked ( instanceof in the generated code) in any order and still provide a stable result ⇒ determinism. 使用类,生成器可以通过它们的继承树(从最特定的派生到最不具体)对它们进行排序,并且可以安全地假设其中没有特定继承关系的2个地方是完全不同的,所以它们可以是以任何顺序检查(生成的代码中的instanceof )并仍然提供稳定的结果⇒确定性。

Disclaimer: I'm the one who reported the ordering issue and then provided the patch , but Place was already a class. 免责声明:我是报告订购问题然后提供补丁的人 ,但Place已经是一个类。

I can't speak for the GWT team, but the only reason there seems to be for this abstract class is to force a definition of NOWHERE. 我不能代表GWT团队,但这个抽象类似乎唯一的原因是强制定义NOWHERE。

As you've found out, using abstract classes in this way forces you in to a class hierarchy that may not be appropriate for your business model. 正如您所知,以这种方式使用抽象类会强制您进入可能不适合您的业务模型的类层次结构。 Therefore, in general, if the abstract class were really completely empty, there would be no purpose at all. 因此,一般来说,如果抽象类真的完全是空的,那么就没有任何目的。

This example is especially strange though because an interface is a contract. 这个例子特别奇怪,因为接口是契约。 The GWT Place has no interface and therefore no contract. GWT Place没有接口,因此没有合同。 Their javadoc states: 他们的javadoc说:

"Represents a bookmarkable location in an app" “代表应用中的可收藏位置”

I would have expected some contract defined to deal with this scenario. 我本来期望定义一些合同来处理这种情况。 What methods would a bookmarkable location require? 可收藏的位置需要哪些方法? If this is just a marker, like Serializable , I would definitely expect it to be an interface rather than an abstract class. 如果这只是一个标记,比如Serializable ,我肯定会期望它是一个接口而不是一个抽象类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM