简体   繁体   English

将方法委托给Java中的子类

[英]Delegating methods to subclasses in Java

I have a superclass Shape, and classes Triangle, Square, etc. extend Shape. 我有一个超类Shape,而Triangle,Square等类则扩展Shape。 I have two current issues: 我有两个当前问题:

  1. My method Triangle extends Shape does not compile. 我的方法Triangle extends Shape无法编译。 It has to return a Shape, not a Triangle. 它必须返回一个Shape而不是Triangle。
  2. I want to hide this method. 我想隐藏这种方法。 It should only be callable from the Shape superclass. 它只能从Shape超类中调用。
public class Shape {
  public static Shape createShapeFromXML(String xml) {
    String type = parse(xml);
      if (type.equals("Triangle") {
        Triangle.createShapeFromXML(xml);
      } else if (...) {
      // ...
    }
  }
}

public class Triangle extends Shape {
  public static Triangle createShapeFromXML(String xml) {
    ....
  }
}

public static void main(String[] args) {
  String xml = ...
  Shape s = Shape.createShapeFromXML(xml);
}

How can I resolve these issues? 我该如何解决这些问题?

why don't you keep the one static method in the superclass, and have it return the appropriate Shape subclass? 您为什么不在超类中保留一个静态方法,并让它返回适当的Shape子类? The signature would stay the same because Triangles have an is-a relationship to Shape. 签名将保持不变,因为Triangles与Shape具有is-a关系。

You could make the method on the superclass private to get the access restriction you want... 您可以将超类上的方法设为私有,以获取所需的访问限制...

Another approach would be to use the Factory pattern. 另一种方法是使用Factory模式。 You could have a ShapeFactory... This is a good idea because creating the xml parsing is not a concern of the Shape classes. 您可能有一个ShapeFactory ...这是一个好主意,因为创建xml解析与Shape类无关。 Separate your concerns. 分开关注。 The wikipedia link is good at describing the pattern, but you might want a simpler example. Wikipedia链接擅长描述模式,但您可能需要一个更简单的示例。 See this . 看到这个

// 2. I want to hide this method. // 2.我要隐藏此方法。 It should only be callable from superclass Shape 它只能从超类Shape调用

You can make the Shape method final in order to lock down the implementation. 您可以使Shape方法成为final方法,以锁定实现。 Even your overloaded method that returns a subclass type ( Triangle in your example) would be flagged by the compiler. 即使您的返回子类类型的重载方法(在示例中为Triangle )也会被编译器标记。

public static final Shape createShapeFromXML(String xml) { ... }

EDIT: 编辑:

in response to the conversation in the comments, for evidence I provide the following: 为了回应评论中的对话,为提供证据,我提供以下内容:

public class Shape {
   public static final Shape createShapeFromXML(String xml) {
      if (xml.equals("Triangle")) {//removed parse for demo compliation
         return Triangle.createShapeFromXML(xml);
      } else {
         return new Shape();
      }
   }
}

public class Triangle extends Shape{
   public static Triangle createShapeFromXML(String xml) {
      return new Triangle();
   }
} 

trying to compile the above will result in a compiler error: 尝试编译以上内容将导致编译器错误:

mybox:src akf$ javac Triangle.java
Triangle.java:3: createShapeFromXML(java.lang.String) in Triangle cannot override createShapeFromXML(java.lang.String) in Shape; overridden method is static final
     public static Triangle createShapeFromXML(String xml) {
                                ^
1 error

This can be explained using the JLS by referencing two sections: 可以通过参考两个部分使用JLS进行解释:

from 8.4.6.2 Hiding (by Class Methods) : 8.4.6.2隐藏(通过类方法)

If a class declares a static method, then the declaration of that method is said to hide any and all methods with the same signature in the superclasses and superinterfaces of the class that would otherwise be accessible to code in the class. 如果一个类声明了一个静态方法,则称该方法的声明隐藏了该类的超类和超接口中具有相同签名的所有方法,否则该类中的代码将可以访问这些方法。

and then from 8.4.3.3 final Methods : 然后从8.4.3.3 final方法开始

A method can be declared final to prevent subclasses from overriding or hiding it. 可以将方法声明为final,以防止子类覆盖或隐藏它。 It is a compile-time error to attempt to override or hide a final method. 尝试覆盖或隐藏最终方法是编译时错误。

Putting the two together, adding final to the signature of a static method will protect that method from being hidden by subclasses. 将两者放在一起,将final添加到静态方法的签名中,可以保护该方法不被子类隐藏。 It will enforce compile-time checking. 它将强制执行编译时检查。

To make your code compile you need to declare public static Shape createShapeFromXML(String xml) in the Triangle class. 为了使代码编译,您需要在Triangle类中声明public static Shape createShapeFromXML(String xml)


public class Shape {

    public static void main(String[] args) {
            String xml = "Triangle";
            Shape s = Shape.createShapeFromXML(xml);
            System.out.println(s.toString());
    }

    public static Shape createShapeFromXML(String xml) {
       Shape aShape = null;

       if (xml.equals("Triangle")) {
         aShape = Triangle.createShapeFromXML(xml);
       }
       return aShape;
     }
 }

class Triangle extends Shape {

    public static Shape createShapeFromXML(String xml) {
         return new Triangle();
    }

    @Override
    public String toString() {
       return "Triangle";
    }
 }

The System.out.println(s.toString()); System.out.println(s.toString()); in the main method outputs "Triangle", this proves that a Triangle shape is being created. 在main方法的输出“ Triangle”中,这证明正在创建Triangle形状。

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

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