In the Java class below two search methods are defined. They are differentiated based on searchSpec type. My understanding is, when the search method is called from somewhere, it is checked what is the type of searchSpec and depending on that type the correct search method is invoked.
Now, I have implemented this class in Python using abstract base classes. Both GuitarSpec and MandolinSpec are inheriting from my abstract base class, and have their own matches method. But I don't have the possibility to create two search methods in the Inventory because the type of the arguments are irrelevant in Python.
That means in Python when the search method of Inventory is invoked, there is a possibility that a list containing both Guitar and Mandolin objects would return. So, I like to know how can I get the same advantage of Java type checking of inputs somehow implemented in Python, so that I can ensure the search method returns only instruments of the same class type.
This is the Java class
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;
}
}
This is the Python class
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