2013-03-10 30 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