禁用派生类上的继承方法

发布于 2024-10-28 05:23:14 字数 397 浏览 4 评论 0原文

在 Java 派生类中,有什么方法可以“禁用”从基类继承的方法和/或字段吗?

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

。 Shape 有一个 rotate() 方法。但我不希望 rotate() 可供 Circle 的用户使用,因为它毫无意义,也不希望 UpwardArrow 的用户使用,因为我不希望 UpwardArrow 能够旋转。

Is there any way to, in a Java derived class, "disable" a method and/or field that is otherwise inherited from a base class?

For example, say you have a Shape base class that has a rotate() method. You also have various types derived from the Shape class: Square, Circle, UpwardArrow, etc.

Shape has a rotate() method. But I don't want rotate() to be available to the users of Circle, because it's pointless, or users of UpwardArrow, because I don't want UpwardArrow to be able to rotate.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

知你几分 2024-11-04 05:23:15

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

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

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

,那么您将 Circle 传递给该方法

handleShape(new Circle());

会发生什么?本质上,您要求对 Java 的类型系统进行根本性的改变。

如果 Circle 是一个 Shape 并且不应该旋转,那么这可能意味着 Shape 设计得很糟糕并且不应该有旋转方法。您可以将旋转添加到层次结构中的不同类,例如 RotatableShape,或者可能使用 Rotatable 接口。

I don't think you can disable a method in the way you suggest.

In your example, lets say you have a method that takes a Shape

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

Then you pass a Circle to this method

handleShape(new Circle());

What should happen? Essentially you are asking for a fundamental change to Java's type system.

If Circle is a Shape and shouldn't be rotated then it probably means that Shape was designed poorly and shouldn't have a rotate method. You can add rotate to a different class int the hierarchy like, RotatableShape or possibly use an interface Rotatable.

小姐丶请自重 2024-11-04 05:23:15

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

因此,对于circle,我们有一个旋转函数的存根,因为系统没有变化。不喜欢,太可惜了我推迟了关于点组的测验来写这篇文章。
对于向上箭头,我们抛出一个异常,因为我们不想在单向街道上走错路,而且无论如何这应该是不变的。

就我而言,我是通过从定义四元数的类继承操作来定义 3 维空间中的点。 3维点仅使用四元数的3个虚坐标,如果四元数的实部具有非零值,则将破坏通过3维坐标从四元数继承的渲染算法的重要操作。

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

我的情况属于向上箭头,除非我指向想象。我试图截断派生类,这意味着任何“孙”类(可能继承自旋运算符)将不再一定是四元数。通过在截断派生类的类型转换时修剪基类来避免抛出异常会更优雅。另一种方法是将 3 维坐标定义为具有四元数成员变量的单独类;缺点是实现上有太多的胶水。

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

So there are two possibilities here. One is that you have an object that can rotate, but shows no change in the process. The other is that you have an object that is defined by it's direction. Each ought to be handled separately and in their own way.

So for circle, we have a stub for a rotate function since there is no change in the system. Don't like it, too bad. I'm putting off my quiz on point groups to write this.
For upward arrow, we throw an exception since we don't want to drive the wrong way on a one-way street and this ought to be constant anyway.

In my case, I'm defining a point in 3 dimensional space by inheriting operations from a class defining a quaternion. The 3 dimensional point only uses the 3 imaginary coordinates of the quaternion and if the quaternion has a non-zero value for the real component, it will ruin the vital operations of the rendering algorithm inherited from the quaternion via the 3 dimensional coordinate.

Excuse me for being overly philosophical, however, this question raises a valid point in CS about how this should be handled. As Stephen notes, being able to hide, disable or remove the inherited function in the child class "...would violate the substitutability principle and would break polymorphism."

My case falls under the upward arrow, except I'm pointing into imagination. I am attempting to truncate a derived class, which means any 'grandchild' class (possibly inheriting spin operators) would no longer necessarily be quaternions. It would be more elegant to avoid resorting to throwing exceptions, by trimming the base class at the typecast for a truncating derived class. The alternative would be defining the 3 dimensional coordinate as a separate class with a quaternion member variable; the drawback is that the implementation has too much glue.

Then I can put the new spin operations into the derived class for the 3 dimensional coordinates for the three planes (ij, jk, ik) and then the objects with 3d vertices can be rotated via a loop and an identical member function call for each vertex. You might could keep track of the symmetry on your own, before you start rotating the points defining the surface of sphere, which is why you need to use the stub function and possibly implement your own 'constant' flag.

御守 2024-11-04 05:23:15

我需要同样的东西来定制警报对话框。我需要传递一个仅在显示时刻可用的参数,因此我实现了 show(argument) 方法,但由于超类, show() 也可以工作。存在这样的风险:我可能会在没有参数的情况下意外调用 myDlg.show(),这会导致崩溃。为了确保永远不会在 CustomAlertDialog 类之外调用超类方法,我向其中添加了方法 private static void show(){}。就是这样。

因此,要禁用超方法,请在子类中将其设为私有和静态。在你的情况下,它将是:

 private void rotate(){}

I needed the same thing for a custom alertdialog. I needed to pass an argument that became available only at the show moment, so I implemented my show(argument) method, but show() worked too because of the superclass. There was a risk of that I could invoke myDlg.show() by accident, without an argument, and that would cause a crash. To make sure the superclass method is never called outside my CustomAlertDialog class, I added the method private static void show(){} to it. That's it.

So, to disable a supermethod, make it private and static in the subclass. In your case, it would be:

 private void rotate(){}
∝单色的世界 2024-11-04 05:23:15

有可能,而且很简单。使用组合代替继承:

public class Shape{
   public method1();
   public method2();
   public rotate();
   public method3();
}

public class Circle{
  private Shape shape;

  public Circle(){
    this.shape = new Shape();
  }

  public method1(){
    shape.method1()
  }

  public method2(){
    shape.method2()
  }

  public method3(){
    shape.method3()
  }
}

There is a possibility and it's quite simple. Instead of inheritance use composition:

public class Shape{
   public method1();
   public method2();
   public rotate();
   public method3();
}

public class Circle{
  private Shape shape;

  public Circle(){
    this.shape = new Shape();
  }

  public method1(){
    shape.method1()
  }

  public method2(){
    shape.method2()
  }

  public method3(){
    shape.method3()
  }
}
不念旧人 2024-11-04 05:23:14

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

例如:

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
}

I don't think it is possible.
However you can further refine the Shape class by removing the rotate() method from its specification and instead define another subclass of Shape called RotatableShape and let Circle derive from Shape and all other Rotatable classes from RotatableShape.

e.g:

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
}
云淡风轻 2024-11-04 05:23:14

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

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

You can override the specific method "rotate()" in the class you want to disable this operation, like this

public void rotate() {
    throw new UnsupportedOperationException();
}
萌化 2024-11-04 05:23:14

如果您需要禁用子类中的方法,那么您的类层次结构就很糟糕。任何子类都应该能够顺利地使用其超类的方法。这称为“里氏替换原则”(https://en.wikipedia.org/wiki/Liskov_substitution_principle< /a>)。您可以在此线程中阅读有关此内容的更多信息:https://softwareengineering。 stackexchange.com/questions/219543/should-a-class-know-about-its-subclasses

按照昌杜的建议去做。不要将旋转()放在形状中。相反,创建一个名为 RotatableShape 的 Shape 子类,并在其中放置rotate()。那么Circle可以继承自Shape,而Rectangle可以继承自RotatableShape。

You have a bad class heirarchy if you need to disable methods in child classes. Any subclass should be able to smoothly use the methods of its superclasses. This is called the "Liskov Substitution Principle" (https://en.wikipedia.org/wiki/Liskov_substitution_principle). You can read more about this in this thread: https://softwareengineering.stackexchange.com/questions/219543/should-a-class-know-about-its-subclasses.

Do what Chandu suggests. Don't put rotate() in Shape. Instead, make a subclass of Shape called RotatableShape, and put rotate() in there. Then Circle can inherit from Shape, and Rectangle can inherit from RotatableShape.

如梦初醒的夏天 2024-11-04 05:23:14

不,

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

No.

  • you can pull the method down in only the Circle class (or an interface that is implemented only by that class)
  • you can provide an empty implementations or ones that throw UnsupportedOperationException in the classes that do not support it.
水水月牙 2024-11-04 05:23:14

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

Declaring the same function in the 'child'-class will overwrite the default function declared in the base class. So in your child-class, make a function called rotate() which does nothing, that will overwrite the default behaviour

述情 2024-11-04 05:23:14

你可以对圆使用 empy (什么都不做)方法吗?
对于箭头我会重新考虑对象层次结构

Can you use an empy (does nothing) method for the circle?
For the arrow I would reconsider object hierarchy

故事与诗 2024-11-04 05:23:14

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

另一种选择是引入一个 Rotatable 接口并使用 shape instanceof Rotatable 来做出决定。 (但是,我认为 isRotatable() 方法更灵活。)

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

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

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

One way to deal with this is to define a second method called (say) boolean isRotatable(), and use this to determine whether the rotation controls are made available to the user.

Another option would be to introduce a Rotatable interface and use shape instanceof Rotatable to make the determination. (However, I think the isRotatable() approach is more flexible.)

In either case, you can implement the rotate() method on a class that should never be rotated as:

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

The Java language doesn't provide a way to "remove" or "disable" a method in a subclass. That would violate the substitutability principle and would break polymorphism. A subclass cannot remove visible members from the parent classes API.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文