1

Here the SMS_Store inherits the Message, but every time I call the parent method there is the error:

NoneType object does not have attribute 'read_message'.

and also the object stored in the list returns a None value??

class Message():

    def __init__(self, from_number, time_arrived, text_of_sms):
        self.has_been_viewed=False
        self.from_number= from_number
        self.time_arrived = time_arrived
        self.text_of_sms = text_of_sms

    def getTime(self):
        return self.time_arrived

    def getText(self):
        return self.text_of_sms

    def setView(self):
        self.has_been_viewed = True

    def check_read(self):
        return self.has_been_viewed


class SMS_Store(Message):

    def __init__(self):
        self.list_=[]

    def add_new_arrivals(self,from_number, time_arrived, text_of_sms):
        self.list_.append(Message.__init__(self,from_number,time_arrived,text_of_sms))

    def message_count(self):
        return len(self.list_)

    def get_unread_index(self):
        unread =[]
        for i in range(len(self.list_)):
            if(super(SMS_Store,self).check_read() == False):
                unread.append(i)
        return unread

    def read_message(self,index):
        self.list_[index].getText()

    def delete(self,ints):
        a = int(ints)
        self.list_.pop(a)

    def clear():
        for i in list:
            self.list_.pop(i)

inbox = SMS_Store()
inbox.add_new_arrivals(12,9,'some nights i stay up')
inbox.add_new_arrivals(12,5,'cashing in my bad luck')
inbox.add_new_arrivals(14,7,'somenights i call it a draw')
inbox.add_new_arrivals(56,0,'somenights i wish that my lips could built a castle.')
inbox.read_message(0)
martineau
  • 119,623
  • 25
  • 170
  • 301
masair
  • 11
  • 6
  • Why are you overwriting `__init__()`? – bakatrouble Jul 04 '17 at 12:53
  • 2
    You shouldn't inherit `SMS_Store` from `Message` if you use it for storing a list of instances of `Message` – bakatrouble Jul 04 '17 at 12:55
  • Why are you calling `Message.__init__()` explicitly to create instances of the parent class instead of just using `Message()`? – martineau Jul 04 '17 at 13:37
  • `SMS_Store` isn't a kind of `Message`, it's a container of instances of them (i.e. it _has_ one or more instances of them), therefore it shouldn't be a subclass. – martineau Jul 04 '17 at 13:42
  • @martineau It made sense when you said it like that. Now, i know clearly what i should've done. thanks you very much. – masair Jul 04 '17 at 14:37
  • masair: You're welcome. It's a fairly fundamental concept in OOP design. See [**_HAS-A, IS-A terminology in object oriented language_**](https://stackoverflow.com/questions/2218937/has-a-is-a-terminology-in-object-oriented-language) (and numerous other articles on the subject). – martineau Jul 04 '17 at 14:56

2 Answers2

0

You shouldn't use inheritance in this case. Here's corrected version (also fixed code style):

class Message:
    def __init__(self, from_number, time_arrived, text_of_sms):
        self.has_been_viewed = False
        self.from_number = from_number
        self.time_arrived = time_arrived
        self.text_of_sms = text_of_sms

    def get_time(self):
        return self.time_arrived

    def get_text(self):
        return self.text_of_sms

    def set_view(self):
        self.has_been_viewed = True

    def check_read(self):
        return self.has_been_viewed


class SMSStore:
    def __init__(self):
        self._list = []

    def add_new_arrivals(self, from_number, time_arrived, text_of_sms):
        self._list.append(Message(from_number, time_arrived, text_of_sms))

    def message_count(self):
        return len(self._list)

    def get_unread_index(self):
        return list(filter(lambda m: not m.check_read(), self._list))

    def read_message(self, index):
        return self._list[index].get_text()

    def delete(self, index):
        a = int(index)
        self._list.pop(a)

    def clear(self):
        self._list = []

inbox = SMSStore()
inbox.add_new_arrivals(12, 9, 'some nights i stay up')
inbox.add_new_arrivals(12, 5, 'cashing in my bad luck')
inbox.add_new_arrivals(14, 7, 'somenights i call it a draw')
inbox.add_new_arrivals(56, 0, 'somenights i wish that my lips could built a castle.')
print(inbox.read_message(0))
bakatrouble
  • 1,746
  • 13
  • 19
  • thanks man. and eh sorry for the code style , my first question as you could guess. but out of my curiosity, why can't i use inheritance in this case ... – masair Jul 04 '17 at 13:29
  • Because it has no sense: you have a message, and a list of messages. This list is neither message nor kind of message. – bakatrouble Jul 04 '17 at 13:36
0

It's unclear where that error could be coming from since read_message() is only called by the inbox.read_message(0) statement at the end of your code, which wouldn't produce it (although the return value of the read_message() method is always None, since there's no explicit return statement in it).

Regardless, to answer the titular question, to do that explicitly you would use the super() method—but that's not the problem here which is that the SMS_Store class shouldn't be a subclass of Message at all, since it's not a specialization of the Message class...rather it's a container of Message instances.

Below is reworked version of your code that shows how to separate these two classes and get most if not all of the methods working. It also now mostly follows PEP 8 - Style Guide for Python Code recommendations.

class Message:
    def __init__(self, from_number, time_arrived, text_of_sms):
        self.has_been_viewed = False
        self.from_number = from_number
        self.time_arrived = time_arrived
        self.text_of_sms = text_of_sms

    def get_time(self):
        return self.time_arrived

    def get_text(self):
        return self.text_of_sms

    def set_viewed(self):
        self.has_been_viewed = True

    def check_read(self):
        return self.has_been_viewed


class SMS_Store:
    def __init__(self):
        self.list_ = []

    def add_new_arrival(self, from_number, time_arrived, text_of_sms):
        self.list_.append(Message(from_number, time_arrived, text_of_sms))

    def message_count(self):
        return len(self.list_)

    def get_unread_index(self):
        unread = []
        for (i, message) in enumerate(self.list_):
            if not message.check_read():
                unread.append(i)
        return unread

    def read_message(self, index):
        message_text = self.list_[index].get_text()
        self.list_[index].set_viewed()
        return message_text

    def delete(self, index):
        self.list_.pop(index)

    def clear():
        self.list_.clear()

inbox = SMS_Store()

inbox.add_new_arrival(12, 9, 'some nights i stay up')
inbox.add_new_arrival(12, 5, 'cashing in my bad luck')
inbox.add_new_arrival(14, 7, 'somenights i call it a draw')
inbox.add_new_arrival(56, 0, 'somenights i wish that my lips could built a castle.')

print(inbox.get_unread_index())  # -> [0, 1, 2, 3]
print(inbox.read_message(0))     # -> some nights i stay up
print(inbox.get_unread_index())  # -> [1, 2, 3]
martineau
  • 119,623
  • 25
  • 170
  • 301
  • This is exactly what i was trying to do with my code.oh, this is just beautiful. thank you sir. thanks a million sir.. – masair Jul 04 '17 at 17:05
  • I was really confused why the objects were returning None value. thank you for that explanation too – masair Jul 04 '17 at 17:14
  • masair: Once again, you're welcome. Try not to stay up too late... `;-)` – martineau Jul 04 '17 at 17:23