0

Question

Is there a way to have two classes simultaneously inherit from one another?

Background

I am currently working on a Socket Server project. In this project, I have a two classes, a Server class, and a GUI class. Their purposes are self explanatory. But, I obviously need to have the two classes communicate with one another. In the program, I first declare the Socket_Server class, and then the GUI class.

I asked a similar question, How to Access Functions from Methods in Python, which was never satisfactorily answered. Please try to answer either.

Code and Errors

In the GUI class, I have a textbox called self.message. It is used to send a message to all clients. I attempted to inherit this class by using this syntax:

class Socket_Server(GUI.messageFun):

Next, the GUI class inherits from the Socket_Server -

class GUI(Frame, Socket_Server): 

The second inheritance GUI(Socket_Server) works correctly, but the first one fails.

The Button's command is this

        self.send = Button (self.messageFrame, text = "Send",
                        command = lambda: new_server.send_cmd()) 

new_server is an instance of the Socket_Server class.

The current Error Message is this:

Socket Created
Socket Bind Complete
Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 1410, in __call__
    return self.func(*args)
  File "D:\Python Programs\Sockets\IM Project\Server\Server GUI InDev Class.py", line 129, in <lambda>
    command = lambda: new_server.send_cmd())
  File "D:\Python Programs\Sockets\IM Project\Server\Server GUI InDev Class.py", line 82, in send_cmd
    message = self.message.get("0.0",END)
AttributeError: Socket_Server instance has no attribute 'message'
Community
  • 1
  • 1
xxmbabanexx
  • 8,256
  • 16
  • 40
  • 60
  • **NOTE**: This was probably not the most appropriate title - I am unsure of what to call it. If you have a better idea, feel free to edit it. If you need more code, please comment. – xxmbabanexx Mar 10 '13 at 00:44
  • You seem confused about how object-oriented programming and class hierarchies are supposed to work. For example, you shouldn't try to make `GUI` inherit from `Socket_Server`. That inheritance relationship is saying "GUIs are special cases of socket servers", which isn't true! GUIs are GUIs and servers are servers. I suggest you read some introductory OOP tutorials before you proceed any further. – Benjamin Hodgson Mar 10 '13 at 00:53
  • @poorsod Haha - I thought that no one would know that I am new :) I have read [this one] (http://www.sthurlow.com/python/lesson08/) and am working my way through the [Dev Shed Tutorial on OOP](http://www.daniweb.com/software-development/python/code/216596/a-simple-class-inheritance-example-python). I rented my [Python Book](http://www.amazon.com/Python-Programming-Absolute-Beginner-Edition/dp/1598631128) out to one of my friends at school - I am happy that programming is starting to catch on. Anyways, do you have any other suggestions? – xxmbabanexx Mar 10 '13 at 00:59
  • To help with your searching, you should be using object _composition_ (where classes hold references to instances of other classes), not inheritance. – Benjamin Hodgson Mar 10 '13 at 00:59
  • @poorsod ok... so, are there any places where I can learn about `object composition`? Thanks for the help. – xxmbabanexx Mar 10 '13 at 01:05
  • [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) has a pretty good introduction to OOP. You'll want to read chapters 40-44, I think they'll probably clear up some of the things you're having trouble with. – Benjamin Hodgson Mar 10 '13 at 01:08
  • 1
    And regarding the links in your previous comment - the first one, in my opinion, is full of crap and you should forget everything it told you. The Dev Shed tutorial is a good reference for the syntax but doesn't seem to say much about what OOP is _for_. – Benjamin Hodgson Mar 10 '13 at 01:11

2 Answers2

2

The title of this question is different (and a bit more accurate) than the question you ask at the beginning, but none of them fit with what you want. What you need is to communicate two instances of different classes; that is not inheritance.

When you use inheritance, you should ask yourself if every X is also an Y:

  • Is every Employee a Person? Yes
  • Is every Person an Employee? No
  • Is every Employee a Car? No

With this concept in mind, you may see the third example is the most similar to the relation between GUI and Server. It is because your real question is:

  • Does a GUI instance use a Server object?

If the answer is yes, then the server should be an attribute of your GUI class. In the following example, you can see that GUI calls methods of the Server object, but not the other way around:

import Tkinter as tk
import threading
import socket

class Server():
    def __init__(self):
        self.addresses = [('localhost', 12345)] # All addresses to send data
    def sendtoall(self, data):
        for address in self.addresses:
            self._send(address, data)
    def _send(self, address, data):
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.connect(address)
            sock.sendall(data)
        finally:
            sock.close()

class GUI(tk.Tk):
    def __init__(self, server):
        tk.Tk.__init__(self)
        self.server = server
        self.entry = tk.Entry(self)
        self.button = tk.Button(self, text="Send", command= self.sendmessage)
        self.entry.pack()
        self.button.pack()
    def sendmessage(self):
        message = self.entry.get()
        threading.Thread(target=self.server.sendtoall, args=(message,)).start()

server = Server()
gui = GUI(server)
gui.mainloop()

Edit: This code looks more like a client than a server, so it may be a good idea to rename it to something more similar to the concept you have in mind (e.g., Notifier)

Honest Abe
  • 8,430
  • 4
  • 49
  • 64
A. Rodas
  • 20,171
  • 8
  • 62
  • 72
  • What does `threading.Thread(target=self.server.sendtoall, args=(message,)).start()` mean? Can you please elaborate. Also, thanks for the great example. – xxmbabanexx Mar 10 '13 at 03:32
  • @xxmbabanexx It starts a new thread which executes the `self.server.sendtoall(message)` method. If it tooks too long, the GUI freezes when they run in the same thread. That is why multithreading might be useful in your situation. – A. Rodas Mar 10 '13 at 03:38
  • Sorry for the lack of clarification. I was confused about what `target =` and `args =` meant. Thanks so much for all of the help - this issue has been really bugging me. – xxmbabanexx Mar 10 '13 at 04:36
  • I posted the above question from a mobile device and forgot to notify you. – xxmbabanexx Mar 10 '13 at 16:52
0

The thing you are having trouble with is object orientation. You need to go look up how inheritance works, how objects interact and so fourth its a bit of a hefty subject to cover in one post and is going to take experience to get your head around it.

A side note about tkinter, The command property is Button takes a reference. This is so that every time the button is clicked it will call that function.

self.send = Button (self.messageFrame, text = "Send",
                        command = new_server.send_cmd())

That is saying that command equals the result of new_server.send_cmd().

self.send = Button (self.messageFrame, text = "Send",
                    command = new_server.send_cmd)

This one is saying that command equals a refernce to the send_cmd method.

Stephen
  • 116
  • 5