Search code examples
pythoninheritancesuperclasssuper

Inheritance missing attribute


I get an error saying that the class Guitar doesn't have attribute "type", but it should inherit from super class Equipment.

class Equipment(object):
    __id = 0
    __type = 0
    __brand = 0
    __model = 0
    __serialNumber = 0
    __purchaseCost = 0
    __hireCost = 0
    __available = 0

    def __init__(self, type, brand, model, serialNumber, purchaseCost, hireCost, available):
        self.__type = type
        self.__brand = brand
        self.__model = model
        self.__serialNumber = serialNumber
        self.__purchaseCost = purchaseCost
        self.__hireCost = hireCost
        self.__available = available

    def get_type(self):
        return self.__type
    def set_type(self,type):
        self.__type = type

    def get_brand(self):
        return self.__brand
    def set_brand(self,brand):
        self.__brand = brand

    def get_model(self):
        return self.__brand
    def set_model(self,model):
        self.__model = model

    def get_serialNumber(self):
        return self.__serialNumber
    def set_serialNumber(self,serialNumber):
        self.__serialNumber = serialNumber

    def get_purchaseCost(self):
        return self.__purchaseCost
    def set_purchaseCost(self,purchaseCost):
        self.__purchaseCost = purchaseCost

    def get_hireCost(self):
        return self.__hireCost
    def set_hireCost(self,hireCost):
        self.__hireCost = hireCost

    def get_available(self):
        return self.__available
    def set_available(self,available):
        self.__available = available

    def toString(self):
        return "type : {}, brand : {}, model : {}, serial number : {}, purchase cost : {}, hire cost : {}, available : {}".format(self.__type,
                                                        self.__brand,
                                                        self.__model,
                                                        self.__serialNumber,
                                                        self.__purchaseCost,
                                                        self.__hireCost,
                                                        self.__available)           
class Guitar(Equipment):
    __subtype = 0
    __bodyType = 0
    __pickupType = 0
    __tremSystem = 0

    def __init__(self, type, brand, model, serialNumber, purchaseCost, hireCost, available, subtype, bodyType, pickupType, tremSystem):
        super(Guitar, self).__init__(type, brand, model, serialNumber, purchaseCost, hireCost, available)
        self.__subtype = subtype
        self.__bodyType = bodyType
        self.__pickupType = pickupType
        self.__tremSystem = tremSystem


    def get_subtype(self):
        return self.__subtype
    def set_subtype(self, subtype):
        self.__subtype = subtype

    def get_bodyType(self):
        return self.__bodyType
    def set_bodyType(self, bodyType):
        self.__bodyType = bodyType

    def get_pickupType(self):
        return self.__pickupType
    def set_pickupType(self, pickupType):
        self.__pickupType = pickupType

    def get_tremSystem(self):
        return self.__tremSystem
    def set_tremSystem(self, tremSystem):
        self.__tremSystem = tremSystem

    def toString(self):
        return "type : {}, subtype : {}, brand : {}, model : {}, serial number : {}, purchase cost : {}, hire cost : {}, available : {}, body type : {}, pickup type : {}, trem system : {}".format(self.__type,
                                self.__subtype,
                                self.__brand,
                                self.__model,
                                self.__serialNumber,
                                self.__purchaseCost,
                                self.__hireCost,
                                self.__available,
                                self.__bodyType,
                                self.__pickupType,
                                self.__tremSystem)  

def main():
    type = input("please enter type: ")
    brand = input("please enter brand: ")
    model = input("please enter model: ")
    serialNumber = input("please enter serial number: ")
    purchaseCost = input("please enter purchase cost: ")
    hireCost = input("please enter hire cost: ")
    available = input("is item available: ")

    if type == "guitar":
        subtype = input("please enter subtype: ")
        bodyType = input("please enter body type: ")
        pickupType = input("please enter pickup config: ")
        tremSystem = input("please enter trem system: ")


    guitar = Guitar(type, brand, model, serialNumber, purchaseCost, hireCost, available, subtype, bodyType, pickupType, tremSystem)

    print(guitar.toString())

main()

I did the same with the Equipment class, so I think it must be an inheritance thing.


Solution

  • You prefixed all your attribute names with two underscores. This triggers a name mangling mechanism that adds the class name to the attribute name, so child classes cannot override them. This is by design and is meant to avoid accidental overrides (kind of like a "private final" in Java)

    So the solution here is to get rid of these underscores. Python has no real access restriction mechanism (the closer is the name mangling thing explained above) and relies on a simple naming convention: names with a single leading underscore are considered as "not part of the public api" (equivalent of a "protected" in other languages) so that's possibly what you want here.

    This being said, you don't even need this here. Python has a strong support for computed attributes so you can as well remove all your getters/setters and use plain attributes instead, you'll always have the choice to turn them into computed ones latter if needed.