0

I wish I could do 2 things:

    1. Create as many times of the Child class from an instance of the Parent class (What I can do)
    1. Call a method of the Parent class from an instance of the Child class (What I can't do)

To illustrate my problem, I created 2 instances of the class Parent to which I add an instance of the class Child to each.

from datetime import datetime, timedelta


class Child:

    def __init__(self):
        pass

    def ask_time(self):                     # This function doesn't work,
        return self.read_time()             # But I would like to be able to call here the "read_time()" method of the class "Parent"


class Parent:

    def __init__(self, name, minutes_fast):
        self.name = name
        self.minutes_fast = minutes_fast
        self.children = {}

    def add_child(self, name):              # Construct "Child" class instance from class "Parent" class instance
        self.children[name] = Child()       # Because of this line, I cannot inherit "class Child (Parent):"

    def get_child(self, name):
        if name not in self.children:
            self.add_child(name)
            return self.children[name]

    def read_time(self):
        current_time = datetime.now()
        delta = timedelta(minutes=self.minutes_fast)
        return (current_time + delta).strftime("%H:%M:%S")


# Add the Parent "James" who is 3 minutes early to his watch, and add him the child "John"
parent1 = Parent("James", 3)
child1 = parent1.get_child("John")

# Add the Parent "Michael" who is 1 minutes early to his watch, and add him the child "Matthew"
parent2 = Parent("Michael", 1)
child2 = parent2.get_child("Matthew")


print(parent1.read_time())
print(parent2.read_time())

In my use case, reading the time is the responsibility of the class Parent. So I added the read_time() method to this one. But an instance of the class Child must be able to request the time from the instance of the class Parent that created it. So I add the ask_time() method to the class Child which calls the read_time() method of the class Parent... Which does not work without inheriting between my classes (from the following way class Child(Parent):).

Which would allow me to do this, and what I now need to do.

print(child1.ask_time())
print(child2.ask_time())

But I don't see how to inherit when class Parent itself depends on the class Child? Thanks for your help !

David
  • 450
  • 3
  • 14
  • 1
    You would need to explicitly pass the `Parent` instance when creating a `Child`; `Child.__init__()` would store it in `self.parent` perhaps, then you could do `self.parent.read_time()`. – jasonharper Jun 11 '21 at 21:43
  • @jasonharper Thanks. It is the same idea as the answer made by Prune – David Jun 11 '21 at 22:37

1 Answers1

3

You have confused functional dependency with class inheritance. You do not have to inherit read_time from Parent. In fact, your implementation shows that this is not sufficient. As you correctly designed this, read_time is an instance attribute: it makes no sense to call read_time without specifying which Parent instance should respond.

You need to give each child a reference to its parent. Include this in add_child:

def add_child(self, name):
    baby = Child(self, name)
    self.children[name] = baby

Change the Child initialization to use the appropraite info:

def __init__(self, parent, name):
    self.parent = parent
    self.name = name

It seems silly to have the child's name be a property only of the parent's list.

Now, when the child needs to ask the time, we have:

def ask_time(self):
    return self.parent.read_time()
Prune
  • 76,765
  • 14
  • 60
  • 81
  • Thanks @Prune, I understand your idea and very clear explanations. Is it best practice to do this? Because I have the impression that by doing this we are overloading the instances of the `class Child`, right? – David Jun 11 '21 at 22:13
  • What do you mean by "overloading the instances"? Standard practice is to design your class relations before you start coding. You conceived of a parent-child relationship, but did not follow the need for references in the class interactions. You might look up UML (unified modeling language) practices to get an idea of how to use the design stage. – Prune Jun 11 '21 at 22:16
  • I mean I have a feeling that instances of the Child class will incorporate more information than necessary. In any case, it fits my use case perfectly. – David Jun 11 '21 at 22:23
  • What do you mean by "but did not follow the need for references in the class interactions"? Does this mean I could do otherwise? – David Jun 11 '21 at 22:26
  • Define "necessary". Yes, you can continue to keep all of the information in the parents. Then every time you want to call `ask_time`, you globally access the `Parent` class, search through all children of all parents, until you find the current `Child` object. That identifies which parent to ask for the time. This is *not* efficient. – Prune Jun 11 '21 at 22:27
  • Yes, you need to define the class interactions, determine what information is necessary for each interaction, decide where that information should be stored (one end, both ends, or a separate common repository), etc. This is not a place for a primer on system design -- it's a bit broad for Stack Overflow. However, you might now want to remove the children's names from the `Parent` objects -- depending on the interactions you have. – Prune Jun 11 '21 at 22:29
  • OK, thanks. One more python notion that I must study! – David Jun 11 '21 at 22:36
  • System design is a software engineering paradigm, not a Python notion. I've done these diagrams for FORTRAN IV and COBOL-68. – Prune Jun 11 '21 at 22:42