特征是类型必须实现的一组要求。您可以将其视为一种契约:符合特征的类型保证其实现特征的所有功能。
特征类似于 Java接口、C++概念、Swift协议和 Rust特征。如果你熟悉其中任何一个功能,Mojo 特征可以解决相同的基本问题。
背景
在 Python 等动态类型语言中,您无需明确声明两个类是相似的。通过示例可以最轻松地展示这一点:
%%python
class Duck:
def quack(self):
print("Quack.")
class StealthCow:
def quack(self):
print("Moo!")
def make_it_quack_python(maybe_a_duck):
try:
maybe_a_duck.quack()
except:
print("Not a duck.")
make_it_quack_python(Duck())
make_it_quack_python(StealthCow())
Duck和类StealthCow没有任何关联,但它们都定义了一个quack()方法,因此它们在函数中的工作方式相同make_it_quack() 。这是因为 Python 使用动态调度 - 它在运行时识别要调用的方法。因此,它make_it_quack_python()不关心您传递给它的类型,只关心它们是否实现了该quack()方法。
在静态类型环境中,这种方法不起作用: fn函数要求您指定每个参数的类型。如果您想在 不使用特征的情况下在 Mojo 中编写此示例,则需要为每种输入类型编写一个函数重载。从这里开始的所有示例都是在 Mojo 中编写的,因此我们只需调用该函数即可 make_it_quack()。
@value
struct Duck:
fn quack(self):
print("Quack")
@value
struct StealthCow:
fn quack(self):
print("Moo!")
fn make_it_quack(definitely_a_duck: Duck):
definitely_a_duck.quack()
fn make_it_quack(not_a_duck: StealthCow):
not_a_duck.quack()
make_it_quack(Duck())
make_it_quack(StealthCow