1. 程式人生 > >python:抽象類和介面

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

關於這個類的解釋在認證.中有說明。另外許可權也差不多的意思,這裡就不再提了。



參考文獻: