昨天看c++,是關于代理類的。
而代理類的,則包含一整套有繼承關系的類。
所以,我突發奇想,不如用繼承來實現菜單。
思路是,有個menu類,然后派生,
一個用以放子菜單,
另一個用以實現綁定函數的菜單。
代碼如下:
# -*- coding:utf-8 -*-
class Menu(object):
def __init__(self,label):
self.label=label
def click(self):
pass
class callbackMenu(Menu):
def __init__(self,label,callback,father=None):
self.label=label
self.rcallback=callback
self.rfather=father
def click(self,*args,**kwds):
print "currentClick",self.label
print
if callable(self.rcallback):
self.rcallback(*args,**kwds)
else:
return None
class subMenu(Menu):
def __init__(self,label,submenu,father=None):
self.label=label
self.rsubmenu=submenu
self.rfather=father
def show(self):
for i,sub in enumerate(self.rsubmenu):
print "[%d] %s"%(i,sub.label)
def click(self):
print "currentMenu",self.label
self.show()
def showfather(p):
if(hasattr(p,"rfather") and p.rfather==None):
print p.label
return
print p.label,'<-',
showfather(p.rfather)
def showfather2(p,symbol='->'):
if p.rfather==None:
print p.label,
return
showfather2(p.rfather,symbol)
print symbol,p.label,
def handle(p):
while True:
print '-'*40
showfather2(p)
print
p.click()
try:
get=raw_input("Input:")
if get in ['q','Q']:
break
get=int(get)
if get==100:
if hasattr(p,"rfather") and p.rfather!=None:
p=p.rfather
continue
if isinstance(p.rsubmenu[get],callbackMenu):
p.rsubmenu[get].click()
elif isinstance(p.rsubmenu[get],subMenu):
fp=p
p=p.rsubmenu[get]
p.rfather=fp
except:
print "Wrong Input"
if __name__=='__main__':
sub=subMenu("sub",[callbackMenu("cb1",None),
callbackMenu("cb2",None)])
sub2=subMenu("sub2",[callbackMenu("cb2_1",None),
callbackMenu("cb2_2",None)])
sub3=subMenu(
"sub3",
[subMenu("subsub1",
[callbackMenu("subcb1",None),
callbackMenu("subcb2",None)]),
subMenu("subsub2",
[callbackMenu("sub2cb1",None),
callbackMenu("sub2cb2",None)])])
main=subMenu("Main",[sub,sub2,sub3])
handle(main)
在這里,我用輸入100來返回上一級菜單。
現在想想,面向對象的設計真夠難的。
第一步抽象就被卡住了。
在沉思錄中,作者常常提示“用類來表示概念”。
但是,現在很猶豫,我的python版本的需不需要繼承呢。
另外,引一句在C++編程規范里的,
“繼承,不是為了重用,而是為了被重用”。
我覺得非常有道理,因為我需要一個指針樣的東西,
來處理各級菜單,如果提供的接口不一樣,就很難用這個
指針了。