代码之家  ›  专栏  ›  技术社区  ›  IUnknown

多态地推断派生类型

  •  1
  • IUnknown  · 技术社区  · 7 年前

    以下情况的推荐设计方法/替代方案是什么:

    BaseCalculator:
    BaseType prepareData()
    useData(BaseType)
    

    派生计算器使用派生类型覆盖基本功能-

    DerivedCalculator1:
    BaseType prepareData(){ return DerivedType1}
    useData(BaseType t1){ DerivedType1 t=(DerivedType1)t1 //typecast  down and proceed....}
    
    DerivedCalculator2
    BaseType prepareData(){ return DerivedType2}
    useData(BaseType t1){ DerivedType2 t=(DerivedType2)t1 //typecast down and proceed....}
    

    有没有一种设计方法可以避免派生类的类型转换——因为它总是为运行时的错误敞开大门?

    1 回复  |  直到 7 年前
        1
  •  0
  •   Justin Albano    7 年前

    另一种方法是将多态行为转移到 BaseType 而不是在 BaseCalculator .例如:

    public interface BaseType {
        public void process(Calculator calc);
    }
    
    public class DerivedType1 implements BaseType {
    
        @Override
        public void process(Calculator calc) {
            // Do something specific to derived type 1
        }
    }
    
    public class DerivedType2 implements BaseType {
    
        @Override
        public void process(Calculator calc) {
            // Do something specific to derived type 2
        }
    }
    
    public class Calculator {
    
        public void doSomething(BaseType bt) {
            bt.process(this);
        }
    }
    

    如果这种类型的解决方案不足,那么更复杂的解决方案是 Visitor Pattern .访客模式允许任意 基本类型 要由任意 基本计算器 使用 double-dispatch 1.问题就在于此 基本计算器 实现必须有一个方法来处理 基本类型 实现。例如:

    public interface BaseType {
        public void process(Calculator calc);
    }
    
    public class DerivedType1 implements BaseType {
    
        @Override
        public void process(Calculator calc) {
            // Do something specific to derived type 1
        }
    }
    
    public class DerivedType2 implements BaseType {
    
        @Override
        public void process(Calculator calc) {
            // Do something specific to derived type 2
        }
    }
    
    public interface BaseCalculator {
        public void handle(DerivedType1 dt);
        public void handle(DerivedType2 dt);
    }
    
    public class DerviedCalculator1 implements BaseCalculator {
    
        @Override
        public void handle(DerivedType1 dt) {
            dt.process(this);
        }
    
        @Override
        public void handle(DerivedType2 dt) {
            dt.process(this);
        }
    }
    
    public class DerviedCalculator2 implements BaseCalculator {
    
        @Override
        public void handle(DerivedType1 dt) {
            dt.process(this);
        }
    
        @Override
        public void handle(DerivedType2 dt) {
            dt.process(this);
        }
    }