2013-03-10 27 views
0

問題如何兩類

之間共享數據有沒有辦法有兩個類彼此同時繼承?

背景

我目前工作的一個套接字服務器項目。在這個項目中,我有兩個班,一個Server班,一個GUI班。他們的目的是自我解釋。但是,我顯然需要讓兩個班級相互溝通。在程序中,我首先聲明Socket_Server類,然後聲明GUI類。

我問了一個類似的問題,How to Access Functions from Methods in Python,這從來沒有令人滿意的答案。請嘗試回答。

代碼和錯誤

GUI類,我有一個名爲self.message.文本框,用來將消息發送給所有客戶端。我試圖通過使用此語法來繼承這個類:

class Socket_Server(GUI.messageFun): 

接下來,GUI類從Socket_Server繼承 -

class GUI(Frame, Socket_Server): 

第二產業GUI(Socket_Server)工作正常,但第一個失敗。

按鈕的命令是這樣的

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

new_serverSocket_Server類的一個實例。

當前的錯誤信息是這樣的:

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' 
+0

**注意**:這可能不是最合適的標題 - 我不確定怎麼稱呼它。如果您有更好的主意,請隨時編輯它。如果您需要更多代碼,請評論。 – xxmbabanexx 2013-03-10 00:44:32

+0

你似乎對如何面向對象編程和類層次結構感到困惑。例如,你不應該試圖讓'GUI'從'Socket_Server'繼承。這種繼承關係是說「GUI是套接字服務器的特例」,這是不正確的! GUI是GUI,服務器是服務器。我建議你在繼續下一步之前閱讀一些介紹性的OOP教程。 – 2013-03-10 00:53:45

+0

@poorsod哈哈 - 我認爲沒有人會知道我是新的:)我已閱讀[這一個](http://www.sthurlow.com/python/lesson08/)和我的方式通過[開發Shed Tutorial on OOP](http://www.daniweb.com/software-development/python/code/216596/a-simple-class-inheritance-example-python)。我將我的[Python Book](http://www.amazon.com/Python-Programming-Absolute-Beginner-Edition/dp/1598631128)租給了我在學校的一位朋友 - 我很高興編程開始抓住上。無論如何,你有任何其他建議嗎? – xxmbabanexx 2013-03-10 00:59:32

回答

0

您有麻煩的事情是面向對象的。你需要去查看繼承是如何工作的,對象是如何相互作用的,以及第四篇文章是否包含在一篇文章中的重要主題,並且將會吸取經驗來解決它。

關於tkinter的一個注意事項,命令屬性是Button作爲參考。這是這樣的,每次點擊按鈕它都會調用該函數。

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

這就是說,命令等於new_server.send_cmd()的結果。

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

這是說,命令等於引用到send_cmd方法。

2

這個問題的標題與您在開始時問的問題不同(並且更準確一些),但是它們都不符合您的要求。你需要的是溝通兩個不同類別的實例;那不是繼承。

當您使用繼承,你應該問自己,如果每個X也是Y:

  • 是每一個EmployeePerson
  • 是每隔PersonEmployee
  • 是的每一個Employee a Car沒有

有了這個概念一點,你可能會看到第三個例子是最相似的GUIServer之間的關係。這是因爲你真正的問題是:

  • GUI實例是否使用Server對象?

如果答案是肯定的,那麼服務器應該是你的GUI類的屬性。在下面的例子中,你可以看到Server對象,它GUI調用方法,而不是周圍的其他方式:

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() 

編輯:這段代碼看起來更像是一個客戶端比服務器,所以它可能是一個好主意,把它重新命名爲更類似於你想到的概念的東西(例如,Notifier

+0

'threading.Thread(target = self.server.sendtoall,args =(message,))。start()'是什麼意思?你能否詳細說明一下。另外,感謝這個偉大的例子。 – xxmbabanexx 2013-03-10 03:32:54

+0

@xxmbabanexx它啓動一個執行'self.server.sendtoall(message)'方法的新線程。如果花費太長時間,GUI在同一個線程中運行時會凍結。這就是爲什麼多線程可能對您的情況有用。 – 2013-03-10 03:38:14

+0

對不起,沒有澄清。我對'target ='和'args ='的含義感到困惑。非常感謝所有的幫助 - 這個問題一直在困擾着我。 – xxmbabanexx 2013-03-10 04:36:15