java - Java 与 Python 中的类方法调用(一般 OO 问题)

标签 java python oop ooad

在Java类中下面两个search方法已定义。它们根据 searchSpec 进行区分类型。我的理解是,当 search方法从某处调用,检查 searchSpec 的类型是什么并根据该类型正确的 search方法被调用。

现在,我已经使用抽象基类在 Python 中实现了此类。两者GuitarSpecMandolinSpec继承 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/

相关文章:

java - 注入(inject)不适用于嵌套对象[Jersey 2.22.1]

python - Pandas 相当于 data.table

java - 通用对象的操作

java - 在当前项目和插件组 org.codehaus.mojo 中找不到前缀为 'exec' 的插件

python - 使用中间件将 Django 应用排除在本地化之外

php - 在 php 中运行 python 脚本

c++ - 使用 final 减少虚方法的开销

JavaScript继承: Setting property of sub-class from method of super class

python - 如何使用 tensorflow 制作经过训练的模型的副本?

java - 删除文件时出现问题