(7)類的封裝 反射方法

2022-08-14 00:48:11 字數 4137 閱讀 2296

1. 什麼是封裝

裝:將屬性裝到乙個容器裡,該容器可以是類也可以是物件

封:指的是將裝到容器裡的物件給隱藏起來,該隱藏是對外不對內的

2. 為何要封裝

隱藏資料屬性的目的

把資料屬性隱藏起來,是為了外使用者不能直接操作屬性,而是通過類內部開闢的介面來間接地操作屬性 我們可以在介面之上附加任意的控制邏輯,從而嚴格控制使用者對屬性的操作

隱藏函式屬性的目的:

3. 如何封裝

在函式名或屬性前加 __或者_

ps:反射取__的函式或者屬性時必須在傳入的字串名前面加『_類名』,否則取不到函式,包括hasattr判斷也同理

ps:如果是_的函式則可以直接用反射系列的方法取值

例:

class ftphandler():

def handle(self):

print('1')

if hasattr(self,"_ftphandler__get"): # hasattr判斷如果有這個函式名,呼叫私有位址的方式是_父類名+私有位址的函式名將名字拼成私有位址的格式

print('yes')

else:

print('輸入錯誤')

def __get(self):

'''收取檔案的函式'''

print('123')

ftp = ftphandler()

ftp.handle()

封裝例項

class foo:

__x=1 #這裡就是封裝

def __init__(self,name,age):

self.__name=name #這裡是封裝

self.__age=age #這裡是封裝

def tell_info(self): #這裡定義乙個函式用來檢視類體內的封裝

print(self.__name,self.__age,self.__x,foo.__x)

print(foo.__x) #這時候已經訪問不到x這個值,外部訪問已經查詢不到

obj=foo('egon',18)

print(obj.__name,obj.__age) #這裡物件也訪問不到,外部訪問已經查詢不到

print(obj.__dict__)

ps:原理就是類的靜態函式、類函式、普通函式、全域性變數以及一些內建的屬性都是放在類__dict__裡的,生成乙個key:value的字典,然後在**執行時候就會以key查詢

但凡__開頭的屬性,在類定義的時候,就會在字典裡加上__開頭存入

obj.tell_info() #類內的函式可以訪問到

# print(foo._foo__x)#通過這樣的方式就可以訪問到,所以不是絕對隱藏

# print(obj._foo__name)

注意:

1. __開頭屬性會在類定義階段檢測語法時發生變形,變形規則: _類名__屬性名

2. 類定義階段之後新增的__開頭的屬性不會變形

3. 在繼承中,父類如果不想讓子類覆蓋自己的方法,可以將方法定義為隱藏的

class foo:

__x = 1 #這裡在定義的時候就發生了變形

def __init__(self, name, age):

self.__name = name #這裡在定義的時候就發生了變形

self.__age = age #這裡在定義的時候就發生了變形

def tell_info(self):

print(self.__name) #這裡在定義的時候就發生了變形

obj=foo('egon',18)

obj.__yyy=111 #類定義之後新增不會發生變形

print(obj.__dict__) #檢視下有沒有變形

print(obj.__yyy) #這裡可以直接訪問到

class foo:

def __f1(self): #在類定義階段變形成foo__f1

print('foo.f1')

def f2(self):

print('foo.f2')#在類定義階段變形成foo__f2

self.__f1() #這裡呼叫自己,不會和bar裡面的f1衝突

class bar(foo):

def __f1(self): #在定義階段變形成bar__f1

print('bar.f1')

obj=bar()

obj.f2()

ps:想訪問的方法就是訪問自己,把方法變成贏藏的,然後在乙個地方呼叫,一定不會和別的同名的衝突,為什麼不會衝突,因為在類定義階段大家都統一進行了變形,變形規則就是自己的類名,所以和別人衝突不了,類名是不會重複的

為什麼要封裝

1、封裝資料屬性

意圖:將資料隱藏起來,從而類的使用者無法直接操作該資料屬性,需要類的設計者在類的內部開闢介面,讓類的使用者用過介面來間接的運算元據,類的設計者可以在介面之上附加任意邏輯,從而嚴格控制類的使用者對屬性的操作

隱藏資料屬性的目的:

class people:

def __init__(self,name,age):

self.__name=name

self.__age=age

def tell_info(self): #類內部開了乙個介面讓外部訪問,還可以定製訪問格式

print('' %(self.__name,self.__age))

def set_info(self,name,age): #類內部開了乙個修改介面,可以限定外部傳入的格式

if type(name) is not str:

print('名字必須是str型別傻叉')

return

if type(age) is not int:

print('年齡必須是int型別傻叉')

return

self.__name=name #這裡就可以限定使用者修改的格式,而不能直接修改

self.__age=age

def del_info(self): #刪除使用者名稱和密碼也是,只能從類內部刪除,將刪除**放入乙個函式,存在類的內部,需要刪除時候呼叫這個函式

del self.__name

del self.__age

obj=people('egon',18)

obj.tell_info()#這裡通過介面訪問到資料

obj.set_info('egon',19)

obj.tell_info()#這裡通過介面修改了資料

obj.del_info()

print(obj.__dict__)

ps:封裝資料可以在介面之上附加任意設計者想要的邏輯,比如嚴格控制使用者對屬性的增刪該查操作,比如修改使用者名字的格式等

2、封裝函式

意圖:比如取款是功能,而這個功能有很多功能組成:插卡、密碼認證、輸入金額、列印賬單、取錢對使用者來說,只需要知道取款這個功能即可,其餘功能我們都可以隱藏起來,很明顯這麼做隔離了複雜度,同時也提公升了安全性

class atm:

def __card(self):

print('插卡')

def __auth(self):

print('使用者認證')

def __input(self):

print('輸入取款金額')

def __print_bill(self):

print('列印賬單')

def __take_money(self):

print('取款')

def withdraw(self):#做了封裝後,直接在類的內部開闢了乙個整合功能的函式,外部呼叫的時候直接呼叫這個函式即可,並不用考慮有多少功能,也看不到有多少功能

self.__card()

self.__auth()

self.__input()

self.__print_bill()

self.__take_money()

a=atm()

a.withdraw()

iOS反射 2 類方法的反射

1.nsobject常用方法 類別判斷,也可以說是動態方法 objc view plain copy student stu student alloc init autorelease iskindofclass判斷物件是否屬於某個類 或者 子類 if stu iskindofclass pers...

NSObject 類的反射,方法反射(十五)

nsobject 類的反射,方法反射用法如下 import ms nsreflect.h import ms person.h import ms student.h implementation ms nsreflect void shownsreflect else 基類 iskindofcla...

註解和反射7 得到Class類的幾種方法

物件照鏡子後可以得到的資訊 某個類的屬性 方法和構造器 某個類到底實現了哪些介面,對於每個類而言,jre都為其保留乙個不變的class型別的物件。乙個class物件包含了特定某個結構 class inte ce enum annotation primitive type void 的有關資訊 st...