在派生类上禁用inheritance的方法

有没有办法在Java派生类中“禁用”从基类inheritance的方法和/或字段?

例如,假设您有一个具有rotate()方法的Shape基类。 您还可以从Shape类派生各种类型: SquareCircleUpwardArrow等。

Shape有一个rotate()方法。 但是我不想让Circle的用户可以使用rotate() ,因为它没有意义,或者是UpwardArrow用户,因为我不希望UpwardArrow能够旋转。

我不认为这是可能的。 但是,您可以通过从其规范中删除rotate()方法来进一步细化Shape类,而是定义另一个名为RotatableShape的Shape 子类 ,并让CircleShapeRotatableShape中的所有其他可旋转类 派生

例如:

 public class Shape{ //all the generic methods except rotate() } public class RotatableShape extends Shape{ public void rotate(){ //Some Code here... } } public class Circle extends Shape{ //Your implementation specific to Circle } public class Rectangle extends RotatableShape{ //Your implementation specific to Rectangle } 

您可以在要禁用此操作的类中覆盖特定方法“rotate()”,如下所示

 public void rotate() { throw new UnsupportedOperationException(); } 

如果你需要在子类中禁用方法,那么你有一个糟糕的类层次结构。 任何子类都应该能够顺利使用其超类的方法。 这被称为“Liskov Substitution Principal”( https://en.wikipedia.org/wiki/Liskov_substitution_principle )。 您可以在此主题中阅读更多相关信息: https : //softwareengineering.stackexchange.com/questions/219543/should-a-class-know-about-its-subclasses 。

做Chandu建议。 不要将rotate()放在Shape中。 相反,创建一个名为RotatableShape的Shape的子类,并在其中放置rotate()。 然后Circle可以从Shapeinheritance,Rectangle可以从RotatableShapeinheritance。

没有。

  • 你可以只在Circle类(或只由该类实现的接口)中拉下方法
  • 您可以提供一个空实现或在不支持它的类中抛出UnsupportedOperationException实现。

在’child’类中声明相同的函数将覆盖在基类中声明的默认函数。 因此,在您的子类中,创建一个名为rotate()的函数,它不会执行任何操作,这将覆盖默认行为

你能用圆圈的empy(什么也不做)方法? 对于箭头,我会重新考虑对象层次结构

解决这个问题的一种方法是定义一个名为(例如) boolean isRotatable()的第二个方法,并使用它来确定旋转控件是否可供用户使用。

另一个选择是引入一个Rotatable接口并使用shape instanceof Rotatable进行确定。 (但是,我认为isRotatable()方法更灵活。)

在任何一种情况下,您都可以在一个永远不应该旋转的类上实现rotate()方法:

 public void rotate() { throw new UnsupportedOperationException("rotate"); } 

Java语言没有提供“删除”或“禁用”子类中的方法的方法。 这将违反可替代性原则,并会破坏多态性。 子类无法从父类API中删除可见成员。

我不认为您可以按照建议的方式禁用方法。

在您的示例中,假设您有一个采用Shape的方法

 public void handleShape(Shape s){ s.rotate(); } 

然后将Circle传递给此方法

 handleShape(new Circle()); 

应该怎么办? 基本上你要求对Java的类型系统进行根本性的改变。

如果Circle是一个Shape并且不应该旋转那么它可能意味着Shape的设计很差并且不应该有旋转方法。 您可以将旋转添加到层次结构中的其他类,例如RotatableShape,也可以使用可循环接口。

所以这里有两种可能性。 一个是你有一个可以旋转的对象,但是在这个过程中没有变化。 另一个是你有一个由它的方向定义的对象。 每一个都应该以自己的方式单独处理。

因此对于 ,我们有一个旋转函数的存根,因为系统没有变化。 不喜欢它,太糟糕了。 我正在推断我的小组测验来写这个。
对于向上箭头 ,我们抛出一个例外,因为我们不想在单行道上以错误的方式行驶而且这应该是不变的。

在我的例子中,我通过从定义四元数的类inheritance操作来定义三维空间中的一个点。 三维点仅使用四元数的3个虚坐标,并且如果四元数对于实部的具有非零值,则将破坏通过三维坐标从四元数inheritance的渲染算法的重要操作。

请原谅我过于哲学,但是,这个问题在CS中提出了一个关于如何处理这个问题的有效观点。 正如斯蒂芬所指出的那样,能够隐藏,禁用或删除子类中的inheritance函数“……会违反替代性原则,并会破坏多态性。”

我的情况属于向上箭头,除了我指向想象力。 我试图截断派生类,这意味着任何’孙子’类(可能inheritance自旋运算符)将不再是四元数。 通过在类型转换处修剪基类来截断派生类,避免诉诸exception会更加优雅。 替代方案是将3维坐标定义为具有四元数成员变量的单独类; 缺点是实施有太多胶水。

然后我可以将新的旋转操作放入三个平面(ij,jk,ik)的三维坐标的派生类中,然后可以通过循环旋转具有3d顶点的对象,并为每个顶点调用相同的成员函数。 在开始旋转定义球体表面的点之前,您可以自己跟踪对称性,这就是为什么需要使用存根函数并可能实现自己的“常量”标志。

我需要自定义alertdialog相同的东西。 我需要传递一个只在演出时才可用的参数,所以我实现了我的show(参数)方法,但show()因为超类而工作。 有可能我无意中调用myDlg.show()而没有参数,这会导致崩溃。 为了确保永远不会在我的CustomAlertDialog类之外调用超类方法,我向它添加了private static void show(){}方法。 而已。

因此,要禁用超级方法,请在子类中将其设置为private和static。 在你的情况下,它将是:

  private void rotate(){}