【问题标题】:Use generics to cast from parent to child on method call在方法调用上使用泛型从父级转换为子级
【发布时间】:2015-12-08 01:20:39
【问题描述】:

我一直在尝试找到一种方法来执行以下操作,但不确定它是否可能。假设我有一个超类和两个具有完全不同且独立的字段的子类(类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 强制转换为方法实现中的子类。问题是我对泛型还不是很熟悉,所以不确定这是否可行或没有解决方案。

【问题讨论】:

    标签: java oop generics inheritance


    【解决方案1】:

    您有几种不同的解决方案,每种解决方案各有利弊。例如:

    • 奇怪地重复出现的模板模式:

      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
        }
      }
      

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

    • 双重调度 - 在大多数使用访问者模式实现的 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
      }
    }
    

    【讨论】:

      【解决方案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
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2015-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-01
        • 2015-10-20
        • 2023-02-07
        • 1970-01-01
        相关资源
        最近更新 更多