在方法调用中使用泛型从父级转换为子级

时间:2015-09-11 13:02:10

标签: java oop generics inheritance

我一直试图找到一种方法来做以下事情,但不确定它是否可能。假设我有一个超类和两个具有完全不同且独立的字段的子类(类Field1Field2):

public abstract class Parent {
    private String field;
    // getters and setters
}

public class Child1 extends Parent {
    private Field1 field1;
}

public class Child2 extends Parent {
    private Field2 field2;
}

现在,我有一个接口,其接受Parent类的方法,以及两个实现该接口的实现Impl1Impl2,但我希望它们接受子类:

public interface IMethod {
    void method(Parent parent);
}

public class Impl1 implements IMethod {
    @Override        
    public void method(Child1 child1) { // like this won't compile
        // implementation using Field1
    }
}

public class Impl2 implements IMethod {
    @Override
    public void method(Child2 child2) { // like this won't compile
        // implementation using Field2
    }
}

我一直在尝试以不同的方式使用泛型来实现这一点,所以我避免从Parent转换到方法实现中的子类。问题是我对仿制药还不是很熟悉,所以不确定这是否可行或者没有解决方案。

2 个答案:

答案 0 :(得分:2)

您需要更改

public interface IMethod {
    void method(Parent parent);
}

public interface IMethod<T extends Parent>{
    void  method(T parent);
}

以及您的实施

public class Impl1 implements IMethod<Child1> {
    @Override        
    public void method(Child1 child1) {
        // implementation using Field1
    }
}

public class Impl2 implements IMethod<Child2> {
    @Override        
    public void method(Child2 child2) {
        // implementation using Field2
    }
}

答案 1 :(得分:1)

这里有几个不同的解决方案,每个都有一些优点和缺点。 e.g:

  • 好奇地反复出现模板模式:

    interface IMethod<Child extends Parent> {
      void method(Child child);
    }
    
    public class Impl1 implements IMethod<Child1> {
      @Override        
      public void method(Child1 child1) {
        // implementation using Field1
      }
    }
    
    public class Impl2 implements IMethod<Child2> {
      @Override
      public void method(Child2 child2) {
          // implementation using Field2
      }
    }
    

    它易于实现和使用,但也不是很灵活 - 每个子类都严格地绑定到它接受作为参数的类。

  • 方法重载:

    interface IMethod {
      void method(Parent parent);
    }
    
    public class Impl implements IMethod {
      @Override        
      public void method(Parent parent) {
        // generic implementation
      }
    
      public void method(Child1 child1) {
        // implementation using Field1
      }
    
      public void method(Child2 child2) {
        // implementation using Field2
      }
    }
    

    这也可以让您轻松扩展功能 - 但它需要在编译时知道确切的传递类型。

  • double displatch - 在大多数OO语言中使用访问者模式实现:

    class Parent {
      private String field;
    
      void visit() {
        // generic implementation
      }
    }
    
    public class Child1 extends Parent {
      private Field1 field1;
    
      @Override
      void visit() {
        // implementation using Field1
      }
    }
    
    interface IMethod {
      void method(Parent parent);
    }
    
    public class Impl implements IMethod {
      @Override        
      public void method(Parent parent) {
        parent.visit();
      }
    }
    

    它适合您的示例,但需要一些样板。

如果您确定必须处理Parent,我建议visitor。但总的来说,你可以使用更简单的东西:

class Parent {
  // fields

  public void handle() {
    // Parent's fields
  }
}

class Child1 extends Parent {
  // fields

  @Override
  public void handle() {
    // Child's fields
  }
}