在java中,是否有允许扩展非抽象类的情况?

当存在类层次结构时,它似乎总是表明代码错误。你同意吗?为什么/为什么不同意?

有帮助吗?

解决方案

我同意Jon和肯特但是,像斯科特斯堡(在有效的C ++),我走得更远。我相信的每堂课应该是abstract,或final 的。也就是说,只有在任何层次的叶类是直接实例确实贴切。所有其他类(在继承即内部节点)是“未完成”,并应被因而abstract

它仅仅是没有意义的用于通常的类来进一步扩展。如果类的一个方面是值得延伸和/或修改,清洁器的方法是取一个类并将它分离成一个abstract基类和一个具体实施可互换

其他提示

有一定时候是有意义的具有非最终的具体类。然而,我同意肯特 - 相信类应该是最后(密封在C#)通过默认,以及Java方法应该默认被最终(因为它们是在C#)

由于肯特说,继承,需要精心的设计和文档 - 这是很容易认为你可以只覆盖一个方法,但不知道在哪个该方法可以从基类被称为的其余部分的情况下,实施

请参阅“你怎么设计一个类继承” 有关此更多的讨论。

此问题同样适用于其他平台,如C#的.NET。还有那些(包括我自己)认为这类型应该是最终的/默认密封,并需要明确启封,允许继承。

通过继承扩展的东西,需要精心的设计,而不是刚刚离开启封类型一样简单。因此,我认为它应该是一个明确的决定,允许继承。

有一个很好的理由,让您的代码的非决赛。许多框架如休眠,弹簧,吉斯有时依赖于它们在运行时动态地延伸的非最终的类。

例如,休眠使用代理为延迟关联加载。 尤其是当它涉及到AOP,你会希望你的类非最终,使拦截器可以连接到它。 还请参阅问题在SO

在这里你最好的参考就是约书亚Bloch的优秀著作“有效的Java”,被称为“设计文档继承,否则禁止它”的项目15。然而,关键的一类扩展是否应允许不“是抽象的”,而是“为它设计时考虑到继承”。有时有两个之间的相关性,但它是第二个这是非常重要的。举一个简单的例子大部分AWT类的被设计成被扩展,即使是那些不是抽象。

布洛赫章的总结是,继承类与父母的互动,可奇怪和不可预料,如果祖先没有设计与继承。因此类应该有两种情况一)班,旨在延长,并有足够的文档来形容它应该怎么做B)类标记为final。在类(一)常常是抽象的,但并非总是如此。对于

在你想确保没有子类的一些情况,在其他情况下,你要确保子类(摘要)。但总有一个类的相当大的一部分,你原作者不关心和不应该关心。这被部分开放/关闭。决定的东西应该被关闭是的将是有原因的完成。

我不同意。如果等级是坏的,有好多是没有理由存在的面向对象的语言。如果你从微软和Sun UI组件库,你一定会找到的继承。是所有的“恶意代码”的定义是什么?不,当然不

继承可能被滥用,但这样可以任何语言功能。关键是要学会如何适当地做事情。

我完全不同意。当具体类知道它们未标记为 Final 的方法的可能返回类型时,类层次结构对于具体类有意义。例如,一个具体类可能有一个子类钩子:

protected SomeType doSomething() {
return null;
}

此 doSomething 保证为 null 或 SomeType 实例。假设您有能力处理 SomeType 实例,但没有在当前类中使用 SomeType 实例的用例,但要知道此功能在子类中非常好,而且大多数内容都是具体的。如果当前类可以直接使用并且默认对其 null 值不执行任何操作,则将当前类设为抽象类是没有意义的。如果您将其设为抽象类,那么您将在这种类型的层次结构中拥有其子级:

  • 抽象基类
    • 默认类(该类可能是非抽象的,仅实现受保护的方法,没有其他任何内容)
    • 其他子类。

因此,当默认类可能是最常见的情况时,您就有一个不能直接使用的抽象基类。在另一个层次结构中,少了一个类,因此可以使用功能而无需创建本质上无用的默认类,因为只需将抽象强制到该类上。

  • 默认类别
    • 其他子类。

现在,当然,层次结构可以被使用和滥用,如果没有清楚地记录事物或类设计得不好,子类可能会遇到问题。但是抽象类也存在同样的问题,你并不能仅仅因为向类中添加“抽象”就解决这个问题。例如,如果上面的“doSomething()”方法的约定要求 SomeType 在通过 getter 和 setter 访问时填充 x、y 和 z 字段,则无论您是否使用返回 null 的具体类,您的子类都会崩溃作为您的基类或抽象类。

设计类层次结构的一般经验法则几乎是一个简单的问卷:

  1. 我的子类中是否需要我提议的超类的行为?(y/n)这是您需要问自己的第一个问题。如果您不需要该行为,则没有理由进行子类化。

  2. 我是否需要子类中提议的超类的状态?(y/n)这是第二个问题。如果状态符合您需要的模型,则这可能是子类化的候选者。

  3. 如果子类是从提议的超类创建的,它真的是一种 IS-A 关系,还是只是继承行为和状态的捷径?这是最后一个问题。如果它只是一个快捷方式,并且您无法将您提议的子类“作为”超类,那么应该避免继承。可以将状态和逻辑复制并粘贴到具有不同根的新类中,或者可以使用委托。

仅当一个类需要行为、状态并且可以被认为是超类的子类 IS-A(n) 实例时,才应将其视为从超类继承。否则,存在其他更适合该目的的选项,尽管它可能需要预先做更多的工作,但从长远来看它更干净。

有一些情况下,我们不希望允许去改变。例如,String类,数学式

我不喜欢继承,因为总有一个更好的方式做同样的事情,但是当你在一个庞大的系统进行维护的变化有时修复与最小的变化代码的最佳方式是扩展一个类一点点。是的,这通常会导致一个糟糕的代码,而是一个工作之一,并没有首先重写个月。所以给人一种维修工尽可能多的灵活性,他可以处理是一个很好的路要走。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top