問題描述:我也是在讀500 Line 里滿的DBDB 的代碼時發現的,python的父類可以調用子類的方法,這跟平常習慣的理解方式很不一樣,所以就查了下原因,記錄如下:
1、現象:
最近使用到了SocketServer.py 這個包,就順便學習一下它的實現,在閱讀的過程中,發現
BaseServer 中的 _handle_request_noblock()函數中 有一句
request, client_address = self.get_request()
而這個 get_request()方法是在繼承於BaseServer的 TCPServer 和UDPServer 中實現的,
三個的關系的定義是:
class BaseServer:
class TCPServer(BaseServer):
class UDPServer(TCPServer):
2、疑問:
父類可以調用子類中的方法么?
還是說我對這里代碼的理解有誤?
希望明白的朋友給我解一下惑或者指引一下相關的資料,謝謝拉!
最近使用到了SocketServer.py 這個包,就順便學習一下它的實現,在閱讀的過程中,發現
BaseServer 中的 _handle_request_noblock()函數中 有一句
request, client_address = self.get_request()
而這個 get_request()方法是在繼承於BaseServer的 TCPServer 和UDPServer 中實現的,
三個的關系的定義是:
class BaseServer:
class TCPServer(BaseServer):
class UDPServer(TCPServer):
2、疑問:
父類可以調用子類中的方法么?
還是說我對這里代碼的理解有誤?
希望明白的朋友給我解一下惑或者指引一下相關的資料,謝謝拉!
第 1 條附言 · 2014-08-01 11:51:06 +08:00
第 2 條附言 · 2014-08-01 14:00:14 +08:00
哦,因為 get_request() 有返回值,所以無法在父類中僅僅的定義一個空函數,不然要報錯
9 回復 | 直到 2014-08-02 00:06:58 +08:00
![]() |
1
不用從"父類可以調用子類中的方法"這種角度去看,而從對象生成以后的執行調用這個角度去看就行了,對象調用的時候 self.get_request() 就是調用自己這個對象里的 get_request() 方法啊,那這個方法具體是哪個,是由對象是從哪個類產生決定的
|
![]() |
2
這里的self不是指BaseServer或者它的實例。
|
![]() |
4
無所謂啊反正是執行的時候才執行的,而不是編譯期
|
![]() |
5
動態類型就是這樣子,只要運行期的對象有該方法就可以。
|
![]() |
6
第二條附言不對吧,就算聲明了這個方法,就pass一下,也不會報錯啊。
都說了python是動態類型,只需要在運行時有這個方法,也就是繼承的TCPServer、UDPServer有這個方法的正確實現就行了。 這里的設計是不是不好的問題,確實不怎么好說。在我的理解,這里的BaseServer不是用來給用戶使用的,Python的文檔里也沒有提到這個東西,所以默認他寫這個基類是給自己方便下面實現TCPServer和UDPServer用的。所以只要他自己去實現對應的方法就行了。 同樣,在Tornado 4.0的源碼里,有很多地方的基類,比如tcpserver.py里214行聲明了handle_stream,在255行調用了,但是只是簡單的raise NotImplementedError()。本人是覺得Tornado的這種方式更加好一些。 |
![]() |
7
@
maemual 同意這位。在看Tornado代碼的時候我也發現了這種raise NotImplementedError()的做法,我覺得這樣會比較好。
|
![]() |
8
聲明同名空方法的方式更符合靜態語言的思想。
從代碼的可讀性來說,這個方法對習慣靜態語言的開發者更友好。 |
![]() |
9
|
(原文地址:https://www.v2ex.com/t/125569)