【问题标题】:Passing in a sub-class to a method but having the super class as the parameter?将子类传递给方法但将超类作为参数?
【发布时间】:2012-10-24 19:30:09
【问题描述】:

我有一个抽象类 Vehicle 有 2 个实现的子类 RedVehicleYellowVehicle

在另一个类中,我有一个 List<Vehicle> 包含两个子类的实例。 我希望能够将一个类类型传递给一个方法,然后使用该类型来决定我想要在List 中对哪组对象执行操作。

由于Class 是通用的,我应该用一些东西对其进行参数化,但是将参数作为父类Vehicle 会停止调用代码的工作,因为exampleMethod 现在需要一种Vehicle,而不是@987654329 的子类@ 或YellowVehicle

我觉得应该有一种干净的方法来做到这一点,那么实现该功能的正确方法是什么?

n.b.我不一定要传入Class 类型,如果有更好的建议我很乐意尝试。

调用代码:

service.exampleMethod(RedVehicle.class);
service.exampleMethod(YellowVehicle.class);

字段/方法:

//List of vehicles
//Vehicle has 2 subclasses, RedVehicle and YellowVehicle
private List<Vehicle> vehicles;

//Having <Vehicle> as the Class parameter stops the calling code working
public void exampleMethod(Class<Vehicle> type) 
{
    for(Vehicle v : vehicles)
    {
        if(v.getClass().equals(type))
        {
            //do something
        }
    }
}

【问题讨论】:

    标签: java oop


    【解决方案1】:

    改为这样做:

    public <T extends Vehicle> void exampleMethod(Class<T> type) 
    

    【讨论】:

    • 我知道这很简单。在返回类型/指向通用源的链接之前是否有一个特殊的名称来表示泛型类型会很好。明天我会尝试并接受,如果它有效,谢谢。
    • 查看 oracle 的泛型介绍或 angelika langer 的 java 泛型常见问题解答。 +1 为 mprivat 的直接解决方案。
    • @DaveBall 感谢 angelika langer 的建议,我知道泛型是一个概念并使用过它们,但从未深入研究过它们,这看起来像是对它们的深入讨论.其他感兴趣的人的链接:angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
    • 这个答案稍加阐述可以找到here
    • @Peanut 它们被称为泛型方法
    【解决方案2】:

    为什么不使用visitor pattern

    那样你

    • 不需要类型标记
    • 让动态调度处理大小写区分(而不是if(v.getClass().equals(type))
    • 更灵活(遵循OCP

    详细说明:

    您的抽象类Vehicle 获得一个方法accept(Visitor v),子类通过在v 上调用适当的方法来实现它。

    public interface Visitor {
      visitRedVehicle(RedVehicle red);
      visitYellowVehicle(YellowVehicle yellow);
    }
    

    使用访问者:

    public class Example {
    
      public void useYellowOnly() {
        exampleMethod(new Visitor() {
            visitRedVehicle(RedVehicle red) {};
            visitYellowVehicle(YellowVehicle yellow) {
                 //...action
            });
      }
      public void exampleMethod(Visitor visitor){
          for(Vehicle v : vehicles) {
              v.accept(visitor);
          }  
      }
    }
    

    【讨论】:

      【解决方案3】:

      接受的答案有效,让我到达了我想去的地方。我想我会添加这个只是为了让任何可能需要它的人更清楚。

      在这种情况下,RevisedExposure 是 Exposure 的子类。我需要使用其中任何一个的列表调用 GetMetadata(),这会产生相同的结果集。

      private async Task<List<Metadata>> GetMetadata<T>(List<T> exposures) where T : Exposure
      

      现在我可以从两个具有不同版本列表的地方调用此方法,就像这样。

      var metadata = await GetExposureMetadata(revisions);
      

      var metadata = await GetExposureMetadata(exposures);
      

      效果很好!

      【讨论】:

        猜你喜欢
        • 2010-09-28
        • 1970-01-01
        • 1970-01-01
        • 2015-12-26
        • 2018-12-11
        • 1970-01-01
        • 2017-04-09
        • 2015-04-26
        • 2016-04-21
        相关资源
        最近更新 更多