pythoninheritance

How to allow any child class to be passed as a parameter in a function that requires its parent class


I'm trying to make an inventory system that will work by having a player have an inventory which is a list of items. I want to make a function that allows adding any object whose parent class is item such as, for example, weapon. While I can technically pass any child of the item class as a parameter, how do I make it clear it can be any child and not only the parent?

This is my current code

class item:
    def __init__(self, weight : int, cost : int, name : int):
        self.weight = weight
        self.cost = cost
        self.name = name

class weapon(item):
    def __init__(self, attackinfo, _weight : int, _cost : int, _name : int):
        super().__init__(_weight, _cost, _name)
        self.attackinfo = attackinfo

class inventory:
    def __init__(self):
        self.items = []
    def additem(self, _item : item):
        self.items.append(item)

inventory1 = inventory()
inventory1.additem(weapon({"dmg" : 3, "range" : 10}, 5, 5, "bow"))


Solution

  • Your type hint already shows that so, in that regards, you have nothing that you need to change. def additem(self, item: Item) means that the item argument can be any instance of the class Item or any of its sub-classes.

    Where your type hints fail is that you have declared name: int and then you pass a str in that argument.

    You can use explicit type hints throughout like this:

    class Item:
        weight: int
        cost: int
        name: str
    
        def __init__(self, weight: int, cost: int, name: str) -> None:
            self.weight = weight
            self.cost = cost
            self.name = name
    
    class Weapon(Item):
        damage: int
        range: int
    
        def __init__(self, weight: int, cost: int, name: str, damage: int, range: int) -> None:
            super().__init__(weight, cost, name)
            self.damage = damage
            self.range = range
    
    class Inventory:
        items: list[Item]
    
        def __init__(self) -> None:
            self.items = []
    
        def additem(self, item: Item) -> None:
            self.items.append(item)
    
    inventory1 = Inventory()
    inventory1.additem(Weapon(5, 5, "bow", 3, 10))
    

    Note: PEP8 suggests using the CapWords convention when naming classes.