Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java继承:如何根据并非所有项都拥有的属性从ArrayList中删除项?_Java_Inheritance_Polymorphism_Subclass_Superclass - Fatal编程技术网

Java继承:如何根据并非所有项都拥有的属性从ArrayList中删除项?

Java继承:如何根据并非所有项都拥有的属性从ArrayList中删除项?,java,inheritance,polymorphism,subclass,superclass,Java,Inheritance,Polymorphism,Subclass,Superclass,我想知道如何编辑我的代码,这样我就可以删除cleanShelf方法中的项目,这不仅取决于项目是否已按日期通过使用,还取决于它们是否已打开。问题是dateOpened属性只属于DiaryFood类型的项目,我不知道如何在我的Shelf类中访问它 食物: 日记食品: public class DiaryFood extends Food { private int dateOpened; public DiaryFood(String name, int calorieAmoun

我想知道如何编辑我的代码,这样我就可以删除cleanShelf方法中的项目,这不仅取决于项目是否已按日期通过使用,还取决于它们是否已打开。问题是dateOpened属性只属于DiaryFood类型的项目,我不知道如何在我的Shelf类中访问它

食物:

日记食品:

public class DiaryFood extends Food {

    private int dateOpened;

    public DiaryFood(String name, int calorieAmount, int useDate, int dateOpened) {
        super(name, calorieAmount, useDate);
        this.dateOpened = dateOpened;
    }

    public int getdateOpened() {
        return dateOpened;
    }
}
蔬菜食品:

public class VegFood extends Food {

    private String colour;

    public VegFood(String name, int calorieAmount, int useDate, String colour) {
        super(name, calorieAmount, useDate);
        this.colour = colour;
    }

}
货架:

public class Shelf {

    ArrayList<Food> food;

    public Shelf() {
        food = new ArrayList<Food>();
    }


    public void addFood(Food product) {
        this.food.add(product);
    }

    public void printShelfDetails() {
        for (Food f : food)
        {
            System.out.println(f.getName() + " " + f.getuseDate());
        }
    }

    public void cleanShelf(int day) {

        ArrayList<Food> foodToRemove = new ArrayList<Food>();

        for (int i = 0; i < food.size(); i++) {
            if (food.get(i).getuseDate() < day) {
                foodToRemove.add(food.get(i));
            }
        }

        food.removeAll(foodToRemove);
    }
}
公共类工具架{
ArrayList食品;
公共货架(){
食品=新ArrayList();
}
公共食品(食品){
本.食品.添加(产品);
}
公共作废打印架详细信息(){
食品(f:食品)
{
System.out.println(f.getName()+“”+f.getuseDate());
}
}
公共货架(国际日){
ArrayList foodToRemove=新建ArrayList();
对于(inti=0;i
如果您想继续操作
食品
声明的类型,并且希望避免操作集合中的特定类型,或者对
日记食品
进行降级,您可以在
食品
类中添加一个返回
null
的方法
GetDateOpen()

您应该将返回的类型从
int
值更改为
Integer
值,以便能够返回
null
值:

public abstract class Food {
       public Integer getdateOpened() {
         return null;
       }
}
在实际具有
dateOpened
字段的具体类中,您可以覆盖它:

@Override
public Integer getdateOpened() {
    return dateOpened;
}
当然,在其他没有
dateOpened
字段的具体类中,可以保留基类的实现:
Food

这样,在循环中,您可以执行以下操作:

    for (int i = 0; i < food.size(); i++) {
        Foot currentFood = food.get(i);
        if (currentFood.getuseDate() < day && currentFood.getDateOpened() != null && yourConditionAboutDateOpened) {
            foodToRemove.add(food.get(i));
        }
    }
for(inti=0;i
  • 您应该检查该项目是否为
    DiaryFood
    instance
    ,并进行适当的日期打开检查
  • cleanself
    方法不是很有效。使用
    iterator
    removeIf
    从列表中删除元素是更好、更干净的选择
  • 请看下面的代码

    food.removeIf(item -> item.getuseDate() < day
                || (item instanceof DiaryFood && ((DiaryFood) item).dateOpened < day));
    
    food.removeIf(item->item.getuseDate()

    Iterator Iterator=food.Iterator();
    while(iterator.hasNext()){
    Food item=iterator.next();
    如果(item.getuseDate()<天
    ||(日粮项目实例)
    &&((日记食品)项目)。开放日期<天){
    iterator.remove();
    }
    }
    
    使用
    instanceof
    和casting可能在几个类中看起来很简单,但是想象一下,如果您有10个子类
    Food
    ,每个子类都有自己的删除逻辑

    将方法
    getDateOpened()
    添加到
    Food
    类中,使其在没有
    dateOpened
    属性的类中返回
    null
    ,会给接口增加不必要的复杂性。用户必须知道,对于某些
    Food
    子类,此方法将返回有效值,而对于其他子类,则不会返回有效值。它也不能很好地扩展子类的数量

    一个类型安全的选择是将决定某种类型的食物应该被移除的逻辑移到该类型本身

    例如,在
    Food
    类中创建方法
    shouldBeRemoved(int)

    public abstract class Food {
        public boolean shouldBeRemoved(int day) {
            return this.useDate < day;
        }
    }
    
    因此,在
    Shelf
    类中,您可以执行以下操作:

    public void cleanShelf(int day) {
        ArrayList<Food> foodToRemove = new ArrayList<Food>();
        for (int i = 0; i < food.size(); i++) {
            if (food.get(i).shouldBeRemoved(day)) {
                foodToRemove.add(food.get(i));
            }
        }
        food.removeAll(foodToRemove);
    }
    

    我不建议这种方法。它在某种程度上增加了公共api的开销。为什么不建议改用
    接口
    呢?不管是否使用接口,如果不想强制转换,您必须更改api。这一切都取决于用户想要什么:执行强制转换或打开合同。这就是为什么我在回答中对它进行了细化。@Adowrath没问题:)两件事:DiaryFood不能使用
    this.useDate
    ,因为它在父类中是私有的。而且,我想你应该提到,在某种程度上,这让事情变得复杂,因为现在不是货架决定“嘿,我不再想要这种食物了!”,而是食物说“嘿,我不再适合了!”。根据你正在从事的项目,这可能根本不是一个问题,也可能是一个非常非常大的问题。
    public abstract class Food {
        public boolean shouldBeRemoved(int day) {
            return this.useDate < day;
        }
    }
    
    public class DiaryFood extends Food {
        @Override
        public boolean shouldBeRemoved(int day) {
            return this.getUseDate() < day || this.dateOpened < day;
        }
    }
    
    public void cleanShelf(int day) {
        ArrayList<Food> foodToRemove = new ArrayList<Food>();
        for (int i = 0; i < food.size(); i++) {
            if (food.get(i).shouldBeRemoved(day)) {
                foodToRemove.add(food.get(i));
            }
        }
        food.removeAll(foodToRemove);
    }
    
    public void cleanShelf(int day) {
        food.removeIf(food -> food.shouldBeRemoved(day));
    }