如何使这种方法更通用

问题描述 投票:0回答:2

我在Java中遇到了一些关于继承的问题。我认为这将是直接的,但它已经让我感到困惑。

我有一个超级类...

public class MyItem {

    private String barCode;
    private String price;

    public String getBarCode() {
        return barCode;
    }

    public void setBarCode(String barCode) {
        this.barCode = barCode;
    }

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }

}

我有这2个子类

public class PromotionalItem extends MyItem {

    private String promotion;

    public String setPromotion(String promotion) {
        this.promotion = promotion;
    }

    public void getPromotion() {
        this.promotion = promotion;
    }

}

public class SellableItem extends MyItem {

    private String quantity;

    public String setQuantity(String quantity) {
        this.quantity = quantity;
    }

    public void getQuantity() {
        this.quantity = quantity;
    }

}

现在我有一个方法,我想把它做成通用的,我想类似这样的方法可能会有用......

public void processItem(MyItem item){
    if(item.getClass().isAssignableFrom(PromotionalItem.class)){
        processPromotionalItem((PromotionalItem)item);
    }
    else{
        processSellableItem((SellableItem)item);
    }
}

但是,当我试图将这些项目投射为它们各自的子类时,我得到了一个ClassCastException。我想这样的东西是可以做的。我是不是错过了什么?有什么办法可以替代做这样的事情?

java inheritance collections casting
2个回答
1
投票

这段代码看起来像一个反模式。我想做的是在MyItem里有一个叫做process的抽象方法,让两个子类都实现这个方法。

public class MyItem {

    private String barCode;
    private String price;

    public String getBarCode() {
        return barCode;
    }

    public void setBarCode(String barCode) {
        this.barCode = barCode;
    }

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }

    public abstract void process();

}

现在,如果你有一个子类,你就必须实现process方法,然后你就可以直接调用process方法,而不用检查它是什么类。

public void processItem(MyItem item){
    item.process();
}

1
投票

使 MyClass 摘要,并添加摘要 process 方法,就像 @JoakimDanielson 建议的那样。然后,在你的子类中,重写该方法并实现你自己的逻辑。

public abstract class MyItem {
    ...
    public abstract void process();
}

public class PromotionalItem extends MyItem {
    ...
    @Override
    public void process() {
        // do whatever
    }
}

 public class SellableItem extends MyItem {
    ...
    @Override
    public void process() {
        // do whatever
    }
}

然后,在你的子类中,覆盖那个方法,实现你自己的逻辑。processItem 方法,只要调用 process:

public void processItem(MyItem item) {
    item.process();
}

0
投票

在你的情况下,你应该使用 instanceof 而不是 isAssignableFrom (但要注意,语法不同,下面会详细介绍)。

isAssignableFrom 检查参数对象是否可以写入函数调用的对象。instanceof 检查左边的对象是否来自同一个类或右边类的子类。当你看过了函数的语法之后,这将会更有意义。instanceof:

if(item instanceof PromotionalItem){
    processPromotionalItem((PromotionalItem)item);
}

简而言之,你的逻辑有点不对。你试图从你的物品类的一个子类投向一个完全不同的子类。


0
投票

使用 instanceof 关键字

if(item instanceof PromotionalItem){
    processPromotionalItem((PromotionalItem) item);
} else if(item instanceof SellableItem) {
    processSellableItem((SellableItem) item);
}

确保你使用 else if 不但 else 因为项目可能是其他东西,而不是 PromotionalItemSellableItem 如果你把它施放到一个不是由它建造的类上,你会得到一个...。ClassCastException

instanceof 是一个关键字,用于检查一个引用变量是否包含给定类型的对象引用。


0
投票

我只谈这个问题,因为有足够多的解决方案(我觉得@Major Ben的那个方案不错

item.getClass().isAssignableFrom(PromotionalItem.class)

这句话的意思是:"我是否可以将动态类的 item 一例 PromotionalItem.“

但现在考虑一下--这合法吗?

MyItem item = new PromotionalItem();

是的,是合法的。所以这将 始终 是真的。因此,你再尝试投向 PromotionalItem,即使实际上是不行的。

也可以看看这个。https:/stackoverflow.coma36579602995907


0
投票

使用抽象类,这是伟大的。我们也可以考虑使用像

public class MyItem<T extends MyItem> {

    private String barCode;
    private String price;

    public String getBarCode() { return barCode; }

    public void setBarCode(String barCode) { this.barCode = barCode; }

    public String getPrice() { return price; }

    public void setPrice(String price) { this.price = price; }

    public void process(T item) {
        if(item instanceof PromotionalItem){
            System.out.println("PromotionalItem");
            //do something for promotionalItem
        } else if(item instanceof SellableItem) {
            System.out.println("SellableItem");
            //do something for SellableItem
        }
    }
}


public class PromotionalItem extends MyItem {

    private String promotion;

    public void setPromotion(String promotion) {
        this.promotion = promotion;
    }

    public String getPromotion() {
        return promotion;
    }
}


public class SellableItem extends MyItem {

    private String quantity;

    public void setQuantity(String quantity) {
        this.quantity = quantity;
    }

    public String getQuantity() {
        return quantity;
    }

}


    @Test
    public void test_porecessItem() {
        PromotionalItem promotionalItem = new PromotionalItem();
        SellableItem sellableItem = new SellableItem();
        MyItem<PromotionalItem> promotionalItemMyItem = new MyItem<>();
        MyItem<SellableItem> sellableItemMyItem = new MyItem<>();
        promotionalItem.process(promotionalItem);
        sellableItemMyItem.process(sellableItem);
    }

对了,这只是我们可以想到的一个方案。

© www.soinside.com 2019 - 2024. All rights reserved.