将方法委托给Java中的子类

时间:2010-12-01 03:10:53

标签: java inheritance

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

  1. 我的方法Triangle extends Shape无法编译。它必须返回一个Shape而不是三角形。
  2. 我想要隐藏此方法。它只能从Shape超类中调用。
  3. 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);
    }
    

    如何解决这些问题?

3 个答案:

答案 0 :(得分:6)

为什么不在超类中保留一个静态方法,并让它返回相应的Shape子类?签名将保持不变,因为三角形与Shape形成了一种关系。

您可以将超类上的方法设为私有,以获得您想要的访问限制...

另一种方法是使用Factory模式。你可以有一个ShapeFactory ...... 这是一个好主意,因为创建xml解析不是Shape类的关注点。分开你的顾虑。维基百科链接擅长描述模式,但您可能想要一个更简单的示例。请参阅this

答案 1 :(得分:2)

  

// 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隐藏(按类方法)

  

如果一个类声明了一个静态方法,那么该方法的声明被称为 hide 任何和所有在超类和超接口中具有相同签名的方法该类中代码可以访问的类。

然后来自 8.4.3.3 final方法

  

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

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

答案 2 :(得分:1)

要使代码编译,您需要在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”,这证明正在创建一个三角形。