在Java类中下面两个search
方法已定义。它们根据 searchSpec
进行区分类型。我的理解是,当 search
方法从某处调用,检查 searchSpec
的类型是什么并根据该类型正确的 search
方法被调用。
现在,我已经使用抽象基类在 Python 中实现了此类。两者GuitarSpec
和MandolinSpec
继承 self 的抽象基类,并拥有自己的 matches
方法。但我不可能创建两个 search
Inventory
中的方法因为参数的类型在 Python 中是不相关的。
这意味着在 Python 中,当 search
方法Inventory
被调用时,有可能包含 Guitar
的列表和Mandolin
对象将会返回。所以,我想知道如何获得与以 Python 方式实现的输入的 Java 类型检查相同的优势,这样我就可以确保 search
方法仅返回相同类类型的工具。
这是Java 类
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class Inventory {
private List inventory;
public Inventory() {
inventory = new LinkedList();
}
public void addInstrument(String serialNumber, double price,
InstrumentSpec spec) {
Instrument instrument = null;
if (spec instanceof GuitarSpec) {
instrument = new Guitar(serialNumber, price, (GuitarSpec)spec);
} else if (spec instanceof MandolinSpec) {
instrument = new Mandolin(serialNumber, price, (MandolinSpec)spec);
}
inventory.add(instrument);
}
public Instrument get(String serialNumber) {
for (Iterator i = inventory.iterator(); i.hasNext(); ) {
Instrument instrument = (Instrument)i.next();
if (instrument.getSerialNumber().equals(serialNumber)) {
return instrument;
}
}
return null;
}
public List search(GuitarSpec searchSpec) {
List matchingGuitars = new LinkedList();
for (Iterator i = inventory.iterator(); i.hasNext(); ) {
Guitar guitar = (Guitar)i.next();
if (guitar.getSpec().matches(searchSpec))
matchingGuitars.add(guitar);
}
return matchingGuitars;
}
public List search(MandolinSpec searchSpec) {
List matchingMandolins = new LinkedList();
for (Iterator i = inventory.iterator(); i.hasNext(); ) {
Mandolin mandolin = (Mandolin)i.next();
if (mandolin.getSpec().matches(searchSpec))
matchingMandolins.add(mandolin);
}
return matchingMandolins;
}
}
这是Python 类
class Inventory:
def __init__(self):
self.instruments: List[Union[Guitar, Mandolin]] = []
def add_instrument(self, serial_number: str, price: float, spec: Union[GuitarSpec, MandolinSpec]):
if isinstance(spec, GuitarSpec):
instrument = Guitar(serial_number, price, spec)
else:
instrument = Mandolin(serial_number, price, spec)
self.instruments.append(instrument)
def get(self, serial_number) -> Union[Guitar, Mandolin, None]:
for instrument in self.instruments:
if instrument.serial_number == serial_number:
return instrument
return None
def search(self, search_spec: Union[GuitarSpec, MandolinSpec]) -> List[Union[Guitar, Mandolin]]:
matching_instruments = []
for instrument in self.instruments:
if instrument.get_spec().matches(search_spec):
matching_instruments.append(instrument)
return matching_instruments
最佳答案
首先要做的事情是:在 Java 代码中,您使用的是原始类型,而不是经过正确类型检查的泛型。例如,
private List inventory;
应该是这样的
private List<? extends Instrument> inventory;
public Inventory() {
inventory = new LinkedList<>();
}
此外,您还使用原始迭代器并最终执行如下操作:
Guitar guitar = (Guitar)i.next();
它只是在编译时发出警告,但会在运行时抛出 ClassCastException。基本上,您遇到的问题与 Python 代码相同。
更改原始类型后,区分工具的一种方法是根据类型和谓词过滤它们,例如像这样的东西:
inventory.stream().filter(item -> item instanceof Guitar).filter(...)
在 Python 中,您可以使用 list comprehension过滤元素。
关于java - Java 与 Python 中的类方法调用(一般 OO 问题),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60420287/