python:抽象類和介面
起因
最近在寫上兩篇restframework的博文中遇到了一個問題,認證和許可權中有一個方法定義必須為固定方法名,不是的話就報錯,我當時並不知道是為什麼,以為是某種特性,也沒有深究,今天在群裡和別人聊天的時候,突然看到其他人也有這個問題,然後一查資料,發現了這確實是一個有點意思的東西。
java中的抽象類和介面
引數 | 抽象類 | 介面 |
---|---|---|
預設的方法實現 | 它可以有預設的方法實現 | 介面完全是抽象的。它根本不存在方法的實現 |
實現 | 子類使用extends關鍵字來繼承抽象類。如果子類不是抽象類的話,它需要提供抽象類中所有宣告的方法的實現。 | 子類使用關鍵字implements來實現介面。它需要提供介面中所有宣告的方法的實現 |
構造器 | 抽象類可以有構造器 | 介面不能有構造器 |
與正常Java類的區別 | 除了你不能例項化抽象類之外,它和普通Java類沒有任何區別 | 介面是完全不同的型別 |
訪問修飾符 | 抽象方法可以有public、protected和default這些修飾符 | 介面方法預設修飾符是public。你不可以使用其它修飾符。 |
main方法 | 抽象方法可以有main方法並且我們可以執行它 | 介面沒有main方法,因此我們不能執行它。 |
多繼承 | 抽象方法可以繼承一個類和實現多個介面 | 介面只可以繼承一個或多個其它介面 |
速度 | 它比介面速度要快 | 介面是稍微有點慢的,因為它需要時間去尋找在類中實現的方法。 |
新增新方法 | 如果你往抽象類中新增新的方法,你可以給它提供預設的實現。因此你不需要改變你現在的程式碼。 | 如果你往介面中新增方法,那麼你必須改變實現該介面的類。 |
用python虛擬碼模擬介面和模型類
介面
Interface IMessage:
def func1(self):
pass
def func2(self):
pass
class Msg(IMessage):
def func1(self):
print('func1')
def func2(self):
print('func1')
上面需要說明的是,假如這是一個介面,它可以內部定義方法,但方法裡不能有值,只能寫pass,而如果有多個函式,那麼它也必須全部是pass,否則就會報錯
下面我們可以定義一個類去繼承這個介面,那麼我們定義的這個類就可以定義引數以及做其它操作,但函式的名字、個數必須和介面中的方法相同,否則約束還是不成立,依然報錯。這是一種約束
抽象類
class abstract IMessage:
def abstract func1(self):
pass
def abstract func2(self):
pass
def func3(self):
print('123')
class Msg(IMessage):
def func1(self):
print('func1')
def func2(self):
print('func1')
在抽象類裡面,可以有抽象方法和非抽象方法,抽象方法為pass,非抽象方法就是普通的函式。那麼當另一個類來繼承這個抽象類時,當前的msg類方法,要全部繼承imassage中的抽象方法,但非抽象方法可寫可不寫,這是一種約束加繼承。
python中的抽象類/抽象方法
from abc import ABCMeta,abstractmethod
class Abstract(metaclass=ABCMeta): # 抽象類
@abstractmethod
def func(self):
pass # 指定了某種規範
class A(Abstract):
def func(self): # 遵守這種規範
print("A")
class B(Abstract):
pass
a = A()
b = B()#報錯,沒有實現抽象方法
在定義抽象類前需要從類庫abc匯入ABCmeta類(即Metaclass for defining Abstract BaseClasses,抽象基類的元類)和abstractmethod類。
python中是沒有介面的,但是有抽象方法和抽象類,通過abc這個模組,另外就是當我們定義了一個這樣的方法時,相當於制定了規則,那麼後來者需要這個規則,否則將會拋異常。
restframework中的約束類
在我們上兩篇博文中,我們再自定義認證函式時,都重寫了
class BaseAuthentication(object):
"""
All authentication classes should extend BaseAuthentication.
"""
def authenticate(self, request):
"""
Authenticate the request and return a two-tuple of (user, token).
"""
raise NotImplementedError(".authenticate() must be overridden.")
也就是因為這個原因,所以我們後面繼承的自定義認證類需要去繼承這個authenticate方法,否則就會報錯,報錯資訊為NotImplementedError,一般基本所有的語言如果沒有去繼承這個約束類中的約束方法,都會報這個錯,但python中的是拋異常而已。我們再來看看我們當初寫的認證類:
from rest_framework import exceptions
from rest_framework.authentication import BaseAuthentication
from .models import Token
class TokenAuth(BaseAuthentication):
def authenticate(self,request):
token = request.GET.get("token")
token_obj = Token.objects.filter(token=token).first()
if not token_obj:
raise exceptions.AuthenticationFailed("驗證失敗123!")
else:
return token_obj.user.name,token_obj.token
關於這個類的解釋在認證.中有說明。另外許可權也差不多的意思,這裡就不再提了。
參考文獻: