如何禁止子类有方法?
How to prohibit a subclass from having a method?
在我的 Java 项目中,我有方法 addType1AndType2()
,其中包含 windows 扩展列表和列表中的 select 对象。创建起来非常复杂且耗时,因为必须滚动并且 xpaths 不断变化。这里有两个列表是实际名称,但由于公司专有信息,我将只称它们为 Tyep1
和 Type2
.
现在我有一个 UpdateType1
class,它使用了 AddType1AndType2
中所有复杂的方法,但与 Type2
没有任何关系。我可以复制 AddType1AndType2
并删除我不需要的所有内容,但那将是复制,并且必须在两个 class 中复制更改。这违背了继承和可重用性的目的。
我可以做一个class UpdateType1 extends AddType1AndType2{}
,我已经做到了。但是仍然有像selectType2Value()
这样的方法在subclass.
中是继承的但是不可能的
如果我执行 @Override
并在子 class 中将 class 声明为私有,我会收到一个错误,提示我无法降低子 [=33= 中的可见性].
知道我能做什么吗?现在我只是放一个 throw new AssertError("Do not use")
但这似乎有点蹩脚。有没有更好的方法甚至会在 运行 时给出编译时错误而不是断言,或者这是最好的方法?
问题是:你的模型是错误的。
继承 不仅仅是将 "A extends B" 放入源代码。 A extends B表示:A"is a"B.
无论何时使用 B 对象,您都应该能够放置 A 对象(称为 Liskov substitution principle)。
长话短说:如果 B 有 A 不应该有的方法...那么你不应该让 A 扩展 B。
所以真正的答案是:你应该退后一步,仔细决定你真正想要分享的方法。你把那些放在你的基地 class。其他任何事情都必须去。您可能会定义其他接口和更多基础 classes,例如
class EnhancedBase extends Base implements AdditionalStuff {
编辑:鉴于您的评论;最好的方法是:
- 创建接口来表示应该一起使用的各种方法组
- 而不是扩展那个基础class,使用组合:创建一个新的class A那个使用 一些 B 对象来实现 one/more 这些新接口。
并记住这是一个很好的例子,为什么 LSP 真的有意义 ;-)
您可以使用 'final' 关键字来禁止在子类中扩展方法。
带有 'final' 修饰符的方法不能在子类中重写。
创建接口
public interface IAddType1 {... /* methods signtatures to add Type1 */}
public interface IAddType2 {... /* methods signtatures to add Type2 */}
public interface IUpdateType1 {... /* methods signtatures to update Type1 */}
那么您在 AddType1AndType2
的当前代码将变成一个基础助手 class:
public abstract class BaseOperationsType1AndType2{
//code originally at AddType1AndType2: methods that add Type1 and Type2
}
那么您的新 AddType1AndType2
class 将是:
public class AddType1AndType2
extends BaseOperationsType1AndType2,
implements IAddType1 , IAddType2 {
//nothing special.
}
而您的新 UpdateType1
可以定义为
public class UpdateType1
extends BaseOperationsType1AndType2
implements IUpdateType1 {
//
}
瞧。
在我的 Java 项目中,我有方法 addType1AndType2()
,其中包含 windows 扩展列表和列表中的 select 对象。创建起来非常复杂且耗时,因为必须滚动并且 xpaths 不断变化。这里有两个列表是实际名称,但由于公司专有信息,我将只称它们为 Tyep1
和 Type2
.
现在我有一个 UpdateType1
class,它使用了 AddType1AndType2
中所有复杂的方法,但与 Type2
没有任何关系。我可以复制 AddType1AndType2
并删除我不需要的所有内容,但那将是复制,并且必须在两个 class 中复制更改。这违背了继承和可重用性的目的。
我可以做一个class UpdateType1 extends AddType1AndType2{}
,我已经做到了。但是仍然有像selectType2Value()
这样的方法在subclass.
如果我执行 @Override
并在子 class 中将 class 声明为私有,我会收到一个错误,提示我无法降低子 [=33= 中的可见性].
知道我能做什么吗?现在我只是放一个 throw new AssertError("Do not use")
但这似乎有点蹩脚。有没有更好的方法甚至会在 运行 时给出编译时错误而不是断言,或者这是最好的方法?
问题是:你的模型是错误的。
继承 不仅仅是将 "A extends B" 放入源代码。 A extends B表示:A"is a"B.
无论何时使用 B 对象,您都应该能够放置 A 对象(称为 Liskov substitution principle)。
长话短说:如果 B 有 A 不应该有的方法...那么你不应该让 A 扩展 B。
所以真正的答案是:你应该退后一步,仔细决定你真正想要分享的方法。你把那些放在你的基地 class。其他任何事情都必须去。您可能会定义其他接口和更多基础 classes,例如
class EnhancedBase extends Base implements AdditionalStuff {
编辑:鉴于您的评论;最好的方法是:
- 创建接口来表示应该一起使用的各种方法组
- 而不是扩展那个基础class,使用组合:创建一个新的class A那个使用 一些 B 对象来实现 one/more 这些新接口。
并记住这是一个很好的例子,为什么 LSP 真的有意义 ;-)
您可以使用 'final' 关键字来禁止在子类中扩展方法。
带有 'final' 修饰符的方法不能在子类中重写。
创建接口
public interface IAddType1 {... /* methods signtatures to add Type1 */}
public interface IAddType2 {... /* methods signtatures to add Type2 */}
public interface IUpdateType1 {... /* methods signtatures to update Type1 */}
那么您在 AddType1AndType2
的当前代码将变成一个基础助手 class:
public abstract class BaseOperationsType1AndType2{
//code originally at AddType1AndType2: methods that add Type1 and Type2
}
那么您的新 AddType1AndType2
class 将是:
public class AddType1AndType2
extends BaseOperationsType1AndType2,
implements IAddType1 , IAddType2 {
//nothing special.
}
而您的新 UpdateType1
可以定义为
public class UpdateType1
extends BaseOperationsType1AndType2
implements IUpdateType1 {
//
}
瞧。