我在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。我想这样的东西是可以做的。我是不是错过了什么?有什么办法可以替代做这样的事情?
这段代码看起来像一个反模式。我想做的是在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();
}
使 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();
}
在你的情况下,你应该使用 instanceof
而不是 isAssignableFrom
(但要注意,语法不同,下面会详细介绍)。
isAssignableFrom
检查参数对象是否可以写入函数调用的对象。instanceof
检查左边的对象是否来自同一个类或右边类的子类。当你看过了函数的语法之后,这将会更有意义。instanceof
:
if(item instanceof PromotionalItem){
processPromotionalItem((PromotionalItem)item);
}
简而言之,你的逻辑有点不对。你试图从你的物品类的一个子类投向一个完全不同的子类。
使用 instanceof
关键字
if(item instanceof PromotionalItem){
processPromotionalItem((PromotionalItem) item);
} else if(item instanceof SellableItem) {
processSellableItem((SellableItem) item);
}
确保你使用
else if
不但else
因为项目可能是其他东西,而不是PromotionalItem
和SellableItem
如果你把它施放到一个不是由它建造的类上,你会得到一个...。ClassCastException
instanceof
是一个关键字,用于检查一个引用变量是否包含给定类型的对象引用。
我只谈这个问题,因为有足够多的解决方案(我觉得@Major Ben的那个方案不错
item.getClass().isAssignableFrom(PromotionalItem.class)
这句话的意思是:"我是否可以将动态类的 item
一例 PromotionalItem
.“
但现在考虑一下--这合法吗?
MyItem item = new PromotionalItem();
是的,是合法的。所以这将 始终 是真的。因此,你再尝试投向 PromotionalItem
,即使实际上是不行的。
使用抽象类,这是伟大的。我们也可以考虑使用像
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);
}
对了,这只是我们可以想到的一个方案。