最近在写上两篇restframework的博文中遇到了一个问题,认证和权限中有一个方法定义必须为固定方法名,不是的话就报错,我当时并不知道是为什么,以为是某种特性,也没有深究,今天在群里和别人聊天的时候,突然看到其他人也有这个问题,然后一查资料,发现了这确实是一个有点意思的东西。
参数 | 抽象类 | 接口 |
---|---|---|
默认的方法实现 | 它可以有默认的方法实现 | 接口完全是抽象的。它根本不存在方法的实现 |
实现 | 子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。 | 子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现 |
构造器 | 抽象类可以有构造器 | 接口不能有构造器 |
与正常Java类的区别 | 除了你不能实例化抽象类之外,它和普通Java类没有任何区别 | 接口是完全不同的类型 |
访问修饰符 | 抽象方法可以有public、protected和default这些修饰符 | 接口方法默认修饰符是public。你不可以使用其它修饰符。 |
main方法 | 抽象方法可以有main方法并且我们可以运行它 | 接口没有main方法,因此我们不能运行它。 |
多继承 | 抽象方法可以继承一个类和实现多个接口 | 接口只可以继承一个或多个其它接口 |
速度 | 它比接口速度要快 | 接口是稍微有点慢的,因为它需要时间去寻找在类中实现的方法。 |
添加新方法 | 如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。 | 如果你往接口中添加方法,那么你必须改变实现该接口的类。 |
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中的抽象方法,但非抽象方法可写可不写,这是一种约束加继承。
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这个模块,另外就是当我们定义了一个这样的方法时,相当于制定了规则,那么后来者需要这个规则,否则将会抛异常。
在我们上两篇博文中,我们再自定义认证函数时,都重写了
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
关于这个类的解释在认证.中有说明。另外权限也差不多的意思,这里就不再提了。
参考文献: