超类方法实现可以依赖于子类字段

时间:2015-10-17 02:03:44

标签: java inheritance interface

我的情况如下。

我有一个接口A,它由B,C,D(B,C,D实现A)继承。

  public interface A{
        public String someMethod();
    }

    class B implements A{
        ObjectType1 model;

        @Override
        public String someMethod(){
            if(model instanceof X){
                System.out.print(true);
            }
        }
    }

    class C implements A{
         ObjectType2 model;

        @Override
        public String someMethod(){
            if(model instanceof X){
                System.out.print(true);
            }
    }

    class D implements A{
     ObjectType3 model;

        @Override
        public String someMethod(){
            if(model instanceof X){
                System.out.print(true);
            }
    }

正如您所看到的,所有方法实现都是相同的。所以我在复制代码。我的计划是将方法移动到A并使A成为抽象类。但问题是我的方法取决于模型领域。那么我可以选择哪些代码更好?

bdw类A,B,C也扩展并实现其他类。

修改

代码修改。检查字段

6 个答案:

答案 0 :(得分:1)

我没有看到与model字段将接口A转换为抽象类相关的任何问题。

如果子类中的方法相同,则无需重新实现该方法,除非您想要更改其行为(覆盖它)。

public abstract class A {

    // Make it protected so it can accessible by subclasses
    protected Object model;

    // Common behavior that will be inherited by subclasses
    public String someMethod() {
        if (model instanceof X) {
            return "x";
        } else {
            return "not x";
        }
    }
}

public class B extends A {

    // Subclasses may access superclasses fields if protected or public.
    public void someOtherMethod() {
        System.out.println(super.model.toString());
    }

}

public class C extends A {

    // You may wish to override a parent's method behavior
    @Override
    public String someMethod() {
        return "subclass implements it different";
    }

}

对于您的新代码示例,如果您确实希望以过程方式执行此操作,则可以创建抽象超类ObjectType,然后父级也可以访问它。

但是我不会这样做。在我看来,这样做与面向对象试图解决的方式完全相反。

通过使用子类来定义行为,您不需要在过程逻辑中执行此操作。那就是根据需要使用对象,继承和覆盖/实现行为的重点。

答案 1 :(得分:0)

使用所述字段创建父类A,并表示所述函数。让其他类扩展A.如果它们的功能相同,则无需覆盖它们。

答案 2 :(得分:0)

要进行重复数据删除,您可以将A作为一个抽象类并在那里移动方法和字段的实现,或者创建一个抽象类,比如E,它实现具有该方法和字段的接口,然后使用B,C和D延伸到E级。

对于依赖于子类的字段的更一般的问题,您可以创建一个抽象方法getModel,子类决定如何实现 - 通过返回模型字段或执行其他操作。

答案 3 :(得分:0)

如果您使用的是Java 8,则可以在接口A中使用default方法,并使用模型的getter方法。

 public interface A{
        default public String someMethod() {
            if(getModel() instanceof X){
                System.out.print(true);
            }
        }

       public Object model getModel();
}

然后在所有子接口中实现getModel方法。

答案 4 :(得分:0)

如果要执行此操作,则必须使model在所有派生对象中具有相同(基本)类型。如果它的类型相同,则可以将model放到基类中。无论如何,如果它们具有不同的派生类型,您将需要一个访问器来获取它。

 interface B {
     BaseModel getModel();

     default public strict doSomething() {
          BaseModel m = getModel();

          // do something with m
     }
 }

 class D implements B {
      DerivedModel model;

      public getModel() {
           return model;
      }
 }

答案 5 :(得分:0)

如果我有机会重构它,我将遵循以下方法,利用Java 8 Default Methods

interface A {
    default String someMethod(X objectType) {
        if (objectType instanceof X) {
            System.out.println(true);
        }
        // return something, for now returning class
        return objectType.getClass().toString();
    }
}

class B implements A {
    @Override
    public String someMethod(X objectType) {
        if (objectType instanceof X) {
            System.out.println(true);
        }
        // return "Hello"
        return "Hello";
    }
}

class C implements A {}

class D implements A {}

<强>用法:

public class Main implements A {
    public static void main(String[] args) {
        B b = new B();
        C c = new C();
        D d = new D();
        Main main = new Main();

        main.call(b);
        main.call(c);
        main.call(d);
    }

    public void call(A clazz) {
        ObjectType1 objectType1 = new ObjectType1();
        String type = clazz.someMethod(objectType1);
        System.out.println(type);
    }
}

interface X {
}

class ObjectType1 implements X {

}