Java 从超级对象列表向下投射备选方案

Java 从超级对象列表向下投射备选方案,java,arraylist,downcast,Java,Arraylist,Downcast,我正在写一个程序来记录一个人有多少资产。每个person类都有一个名为Value\u Item对象的ArrayList 值项是一个简单的对象 class Value_Item { float _value; String _currency; String _type //+getters and setters} 如果不愿意澄清任何事情,我假设上面的代码是自解释的 我从价值项目扩展到几个类别,如股票、基金、现金等。 所有这些都有其不同的属性,例如权益“单价” 我目前存储信息的解决方案

我正在写一个程序来记录一个人有多少资产。每个person类都有一个名为Value\u Item对象的ArrayList

值项是一个简单的对象

class Value_Item
{ float _value;
  String _currency;
  String _type //+getters and setters}
如果不愿意澄清任何事情,我假设上面的代码是自解释的

我从价值项目扩展到几个类别,如股票、基金、现金等。 所有这些都有其不同的属性,例如权益“单价”

我目前存储信息的解决方案是创建一个子类,当我调用超类构造函数设置子类的类型时,当我需要对数据进行操作时,比如获取所有持有资金的单价时,我检查类型并向下转换

乙二醇

然而,我已经读到,向下转换是不受欢迎的,而且解决方案本身也感觉不太优雅,有没有更好的方法来实现java的更“pythonic”的等效功能

然而,我读到不赞成向下投射

的确如此。它只能作为最后手段使用。本质上是因为检查要执行处理的对象类型是不可维护的并且它也会在编译时生成不太安全的代码,因为检查类型只会在运行时发生

有没有更好的方法来实现java的更多功能 “蟒蛇”

在您的案例中,主要的问题是
Value\u Item
代表了一个太宽的概念,这就像您为任何事物定义了一个类
Value

要使用
List
中的元素而不使用downcast是非常困难的

子类化(即使不是其主要角色)可能有助于防止代码重复,但子类化也可能显得无能为力,因为您希望以统一的方式使用子类的对象,但基类太宽

对于将元素类型声明为公共基类型的集合/数组,有两种防止向下转换的已知方法:

1) 在基类方法中移动行为。
2) 未在同一集合/数组中收集所有子类实例


1) 在基类方法中移动行为

假设以下摘录是所有子类都要进行的计算的一部分,但每个子类都有自己的字段/方法:

if(_value_item.getType()=="FUND){
  Fund fund = (Fund) _value_item 
  float unit_price = fund.getUnitPrice()}
}
您可以在
ValueItem
中引入抽象
compute()
方法:

public class ValueItem{
    public abstract float compute();
    // ...
}
for (ValueItem valueItem : valueItems){
     float computation = valueItem.compute();
     // ....
}
子类将实现它:

public class Cash extends ValueItem{
    @Override
    public float compute(){
       // ...
    }
    // ...
}

public class Equity extends ValueItem{
    @Override
    public float compute(){
       // ...
    }
    // ...
}
现在,您可以对
列表的任何元素(或所有元素)调用
compute()
方法:

public class ValueItem{
    public abstract float compute();
    // ...
}
for (ValueItem valueItem : valueItems){
     float computation = valueItem.compute();
     // ....
}
2) 未在同一集合/数组中收集所有子类实例

您确实可以将
列表
拆分为多个部分,以将应该统一操作的内容组合在一起

还要注意的是,如果可以统一操作多种类型的项目,您可以为它们引入一个通用的接口。
例如,假设
股票
基金
可以统一操作,因为它们属于同一个特定概念:
UnitPricable
,假设
现金
是一个特定的概念,有其自己的表示/操作方式,您可以得到如下结果:

public class Cash extends ValueItem{
   ...
}

public class Equity extends ValueItem implements UnitPricable{
   ...
}

public class Fund extends ValueItem implements UnitPricable{
   ...
}


public class Person{
   private List<Cash> cashes = new ArrayList<>();
   // the next one groups two kind of subclasses
   private List<UnitPricable> unitPricables = new ArrayList<>();
   ....

   // operations that works on the Cash subclass instances
   public void computeCashes(){
     for (Cash cash : cashes){
        ... = cash.getSpecificCashField();               
        ... = cash.specificCashMethod();               
        ...
     }
   }

   // operations that work on multiple subclasses instances : Fund and Entity
   public void computeUnitPricables(){
     for (UnitPricable up: unitPricables){
        ... = up.getUnitPrice();               
        ... = up.specificUnitPriceMethod();               
        ...
     }
   }
}
公共类现金项目{
...
}
公共类权益扩展价值项目实现单位价格{
...
}
公共类基金扩展价值项目实施单位定价{
...
}
公共阶层人士{
私有列表现金=新的ArrayList();
//接下来的一组是两类子类
private List unitPricables=new ArrayList();
....
//处理Cash子类实例的操作
公共作废计算现金(){
用于(现金:现金){
…=cash.getSpecificCashField();
…=cash.specificCashMethod();
...
}
}
//操作多个子类实例:基金和实体
公共无效computeUnitPricables(){
用于(UnitPricable up:unitPricables){
…=up.getUnitPrice();
…=up.specificUnitPriceMethod();
...
}
}
}
然而,我读到不赞成向下投射

的确如此。它只能作为最后手段使用。本质上是因为检查要执行处理的对象类型是不可维护的并且它也会在编译时生成不太安全的代码,因为检查类型只会在运行时发生

有没有更好的方法来实现java的更多功能 “蟒蛇”

在您的案例中,主要的问题是
Value\u Item
代表了一个太宽的概念,这就像您为任何事物定义了一个类
Value

要使用
List
中的元素而不使用downcast是非常困难的

子类化(即使不是其主要角色)可能有助于防止代码重复,但子类化也可能显得无能为力,因为您希望以统一的方式使用子类的对象,但基类太宽

对于将元素类型声明为公共基类型的集合/数组,有两种防止向下转换的已知方法:

1) 在基类方法中移动行为。
2) 未在同一集合/数组中收集所有子类实例


1) 在基类方法中移动行为

假设以下摘录是所有子类都要进行的计算的一部分,但每个子类都有自己的字段/方法:

if(_value_item.getType()=="FUND){
  Fund fund = (Fund) _value_item 
  float unit_price = fund.getUnitPrice()}
}
您可以在
ValueItem
中引入抽象
compute()
方法:

public class ValueItem{
    public abstract float compute();
    // ...
}
for (ValueItem valueItem : valueItems){
     float computation = valueItem.compute();
     // ....
}
子类将实现它:

public class Cash extends ValueItem{
    @Override
    public float compute(){
       // ...
    }
    // ...
}

public class Equity extends ValueItem{
    @Override
    public float compute(){
       // ...
    }
    // ...
}
现在,您可以对
列表的任何元素(或所有元素)调用
compute()
方法:

public class ValueItem{
    public abstract float compute();
    // ...
}
for (ValueItem valueItem : valueItems){
     float computation = valueItem.compute();
     // ....
}
2) 未在同一集合/数组中收集所有子类实例

您确实可以将
列表
拆分为多个部分,以将应该统一操作的内容组合在一起