繁体   English   中英

将方法委托给Java中的子类

[英]Delegating methods to subclasses in Java

我有一个超类Shape,而Triangle,Square等类则扩展Shape。 我有两个当前问题:

  1. 我的方法Triangle extends Shape无法编译。 它必须返回一个Shape而不是Triangle。
  2. 我想隐藏这种方法。 它只能从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);
}

我该如何解决这些问题?

您为什么不在超类中保留一个静态方法,并让它返回适当的Shape子类? 签名将保持不变,因为Triangles与Shape具有is-a关系。

您可以将超类上的方法设为私有,以获取所需的访问限制...

另一种方法是使用Factory模式。 您可能有一个ShapeFactory ...这是一个好主意,因为创建xml解析与Shape类无关。 分开关注。 Wikipedia链接擅长描述模式,但您可能需要一个更简单的示例。 看到这个

// 2.我要隐藏此方法。 它只能从超类Shape调用

您可以使Shape方法成为final方法,以锁定实现。 即使您的返回子类类型的重载方法(在示例中为Triangle )也会被编译器标记。

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

编辑:

为了回应评论中的对话,为提供证据,我提供以下内容:

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();
   }
} 

尝试编译以上内容将导致编译器错误:

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

可以通过参考两个部分使用JLS进行解释:

8.4.6.2隐藏(通过类方法)

如果一个类声明了一个静态方法,则称该方法的声明隐藏了该类的超类和超接口中具有相同签名的所有方法,否则该类中的代码将可以访问这些方法。

然后从8.4.3.3 final方法开始

可以将方法声明为final,以防止子类覆盖或隐藏它。 尝试覆盖或隐藏最终方法是编译时错误。

将两者放在一起,将final添加到静态方法的签名中,可以保护该方法不被子类隐藏。 它将强制执行编译时检查。

为了使代码编译,您需要在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";
    }
 }

System.out.println(s.toString()); 在main方法的输出“ Triangle”中,这证明正在创建Triangle形状。

暂无
暂无

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

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