4

I would like to know if it's possible, and if yes, how to access attribute(s) of a "super" class instance, when having composition implemented.


Example provided below is only to provide idea here and setup common ground on further explanations.

I want to have access to "id" attribute for an instance of MiniVan directly from object "door" (type DoorElement).


My Code

class Car:
    def __init__(self, _id):
        self.id = _id


class CarElement:
    def __init__(self, name):
        self.name = name

    def get_car_id(self):
        # Body which will access value of attribute "id"
        return car_id


class MiniVan(Car):
    def __init__(self, _id):
        super(MiniVan, self).__init__(_id)
        self.door = DoorElement('door')
        self.engine = EngineElement('engine')


class DoorElement(CarElement):
    def __init__(self, name):
        super(DoorElement, self).__init__(name)


class EngineElement(CarElement):
    def __init__(self, name):
        super(EngineElement, self).__init__(name)


def main():
    mini_van = MiniVan(123)
    id_from_door = mini_van.door.get_car_id()
    id_from_engine = mini_van.engine.get_car_id()
    print(id_from_door) # Expected output 123
    print(id_from_engine) # Expected output 123


if __name__ == '__main__':
    main()

Expected:

  • Printed out twice "123"

What I've tried:

  1. Passing required attribute during creating object

I know that I could just define init method with passing "car_id" but for some reasons I would love to avoid it if possible. If not, I would propably just go for it.

  1. to set class attribute, and then call it from CarElement class within classmethod e.g.:
@classmethod
def get_id(cls):
    return Car.id

But issue with this solution is that, I can have many child-classes for Car class (MiniVan, Truck, etc.) and I want have it still working.

  1. Trying to use descriptor
def __get__(self, instance, owner):
    return instance.id

But I could understand it wrong, and actually getter (as far as I understand clean code) should return instance of a class and not any attribute.


Additional Info

  • I will ALWAYS use CarElement (or child classes) instances as attributes of instance of Car (or child classes) instances - different usage will be treated as use-error
  • There can be a lot of different child classes of Car class, but always within inheritance way ( Car <- RacingCar(Car) <- FormulaOneCar(RacingCar) ) but no composition
4
  • You've clearly put a lot of effort into this question, but I would suggest explaining what your desired output is first, and only then showing us your attempted solutions. Commented Feb 10, 2019 at 20:06
  • @Aran-Fey thanks for this feedback. I've already edited question Commented Feb 10, 2019 at 20:29
  • 1
    i suggest adding a generic ‘owner’ or ‘parent’ when creating Car Elements. That allows you to have sub-components such as a car door handle. the car would just be the root ‘object’ without an owner. any solution based on class, rather than instance, relationships will, imho, end up with problems. Commented Feb 11, 2019 at 6:07
  • @JLPeyret Could You provide an example of such? Because I'm not sure if really following Your idea Commented Feb 12, 2019 at 18:59

1 Answer 1

0

In order for your code to work, you would have to initialize all CarElement-s with car_id. Currently, the error you are getting comes from lack of such a variable in the scope of the method. My idea of a change is this:

class CarElement:
    def __init__(self, name, car_id):
        self.name = name
        self.car_id = car_id

    def get_car_id(self):
        # Body which will access value of attribute id
        return self.car_id

I can't see any other magic way.

Sign up to request clarification or add additional context in comments.

4 Comments

Rather than storing the car's id, it's probably a better idea to have a reference to the car object. That way you have access to all of the car's attributes and methods.
Yes, I actually have seen that this output is completely without sense. I know, that I can initialize objects with passing this value as attribute, but question was if there's any other way to access it
As stated in the answer: no. Your attempts look like imposing C++ object model on Python. They are different and incompatible. Python object model is much simpler.
@sophros basing on my experience with using library page_objects exactly as described (Views in app used as classes inheriting from PageObject, and elements defined as instances of PageElement class) I would say it is possible to have such access. In attached link, we are accessing within PageElement attribute SeleniumWebDriver passed as attribute for PageObject (self.w) directly when calling attribute of instantiated view.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.