Sway编程语言-更新中(The Sway Programming Language-Updatin
  • Sway编程语言(The Sway Programming Language)
  • 1. 导言(Introduction)
    • 1.1 安装(Installation)
    • 1.2 Sway快速入门 (Sway Quickstart)
    • 1.3 Fuel工具链 (The Fuel Toolchain)
    • 1.4 一个Forc项目 (A Forc Project)
    • 1.5 标准库 (Standard Library)
  • 2. 示例(Example)
    • 2.1计数器(Counter)
    • 2.2子货币(Subcurrency)
    • 2.3 FizzBuzz
    • 2.4 钱包智能合约(Wallet Smart Contract)
  • 3.Sway编程类型(Sway Program Types)
    • 3.1 合约(Contracts)
    • 3.2 库 (Libraries)
    • 3.3 脚本(Scripts)
    • 3.4 谓词 (Predicates)
  • 4. Sway语言基础 (Sway Language basics)
    • 4.1 变量 (Variables)
    • 4.2 内置类型(Built-in Types)
    • 4.3 常用库类型(Commonly Used Library Types)
    • 4.4 区块链类 (Blockchain Types)
    • 4.5 函数 (Functions)
    • 4.6 结构、元祖和穷举 (Structs, Tuples, and Enums)
    • 4.7 方法和关联函数 (Methods and Associated Functions)
    • 4.8 注释和日志 (Comments and Logging)
    • 4.9 控制流 (Control Flow)
  • 5. 用Sway部署区块链 (Blockchain Development with Sway)
    • 5.1 哈希和加密学 (Hashing and Cryptography)
    • 5.2 合约存储(Contract Storage)
    • 5.3 函数纯度 (Function Purity)
    • 5.4 标识符(Identifiers)
    • 5.5 原生资产(Native Assets)
    • 5.6 访问控制 (Access Control)
    • 5.7 调用合约(Calling Contracts)
  • 6. 高级概念 (Advanced Concepts)
    • 6.1 高级类型 (Advanced Types)
    • 6.2 通用类型 (Generic Types)
    • 6.3 特征 (Traits)
    • 6.4 集 (Assembly)
  • 7. 一般集聚 (Common Collections)
    • 7.1 堆上的向量(Vectors on the Heap)
    • 7.2 存储向量 (Storage Vectors)
    • 7.3 存储映射 (Storage Maps)
  • 8.测试(Testing)
    • 8.1 单元测试(Unit Testing)
    • 8.2 用Rust来测试 (Testing with Rust)
  • 9.应用前端开发 (Application Frontend Development)
    • 9.1 TypeScript SDK
  • 10.Sway应用(Sway Reference)
    • 10.1 编译器内部函数(Compiler Intrinsics)
    • 10.2 属性(Attributes)
    • 10.3 风格向导(Style Guide)
    • 10.4 已知各类问题(Known Issues and Workarounds)
    • 10.5 与Solidity的不同之处 (Differences From Solidity)
    • 10.6 与Rust的不同之处 (Differences From Rust)
    • 10.7 向Sway贡献 (Contributing To Sway)
  • 11. Forc引用 (Forc Reference)
    • 11.1清单参考 (Manifest Reference)
    • 11.2 工作区(Workspaces)
    • 11.3 依赖(Dependencies)
    • 11.4 命令(Commands)
      • 11.4.1 forc-addr2line
      • 11.4.2 forc-build
      • 11.4.3 forc-check
Powered by GitBook
On this page
  • 声明特征 (Declaring a Trait)
  • 实现特征 (Implementing a Trait)
  • 超特征 (Supertraits)
  • 相关条目 (Associated Items)
  • 用例 (Use Cases)
  1. 6. 高级概念 (Advanced Concepts)

6.3 特征 (Traits)

声明特征 (Declaring a Trait)

A trait opts a type into a certain type of behavior or functionality that can be shared among types. This allows for easy reuse of code and generic programming. If you have ever used a typeclass in Haskell, a trait in Rust, or even an interface in Java, these are similar concepts.

特征 trait 将类型选择为可以在类型之间共享的特定类型行为或功能。这使得复用代码和通用编程变得轻松。如果您曾经在 Haskell 中使用过类型类,在 Rust 中使用过特征,甚至在 Java 中使用过接口,那么这些都是类似的概念。

Let's take a look at some code: 让我们看一些代码:

trait Compare {
    fn equals(self, b: Self) -> bool;
} {
    fn not_equals(self, b: Self) -> bool {
        !self.equals(b)
    }
}

We have just declared a trait called Compare. After the name of the trait, there are two blocks of code (a block is code enclosed in { curly brackets }). The first block is the interface surface. The second block is the methods provided by the trait. If a type can provide the methods in the interface surface, then it gets access to the methods in the trait for free! What the above trait is saying is: if you can determine if two values are equal, then for free, you can determine that they are not equal. Note that trait methods have access to the methods defined in the interface surface.

我们刚刚声明了一个名为 Compare 的特征。在特征名称之后,有两个 区块 代码(一个 块 是包含在{ 大括号}中的代码)。第一个块是 界面表面。第二个块是特征提供的 方法。如果一个类型可以提供接口表面中的方法,那么它就可以免费访问特征中的方法!上面的特征是说:如果你可以确定两个值是否相等,那么你可以免费确定它们不相等。请注意,特征方法可以访问接口表面中定义的方法。

实现特征 (Implementing a Trait)

Ok, so I know that numbers can be equal. I want to implement my Compare trait for u64. Let's take a look at how that is done:

好的,所以我知道数字可以相等。我想为 u64 实现我的 Compare 特性。让我们来看看这是如何完成的:

impl Compare for u64 {
    fn equals(self, b: Self) -> bool {
        self == b
    }
}

The above snippet declares all of the methods in the trait Compare for the type u64. Now, we have access to both the equals and not_equals methods for u64, as long as the trait Compare is in scope.

上面的代码片段声明了 u64 类型的特征 Compare 中的所有方法。现在,只要特征 Compare 在范围内,我们就可以访问 u64 的 equals 和 not_equals 方法。

超特征 (Supertraits)

When using multiple traits, scenarios often come up where one trait may require functionality from another trait. This is where supertraits come in as they allow you to require a trait when implementing another trait (ie. a trait with a trait). A good example of this is the Ord trait of the core library of Sway. The Ord trait requires the Eq trait, so Eq is kept as a separate trait as one may decide to implement Eq without implementing other parts of the Ord trait.

当使用多个特征时,经常会出现一个特征可能需要另一个特征功能的情况。这就是超特征的用武之地,因为它们允许您在实现另一个特性时需要一个特性(即具有特性的特性)。一个很好的例子是 Sway 核心库的Ord特征。 Ord 特性需要Eq 特性,因此Eq 保留为一个单独的特性,因为人们可能决定在不实现Ord 特性的其他部分的情况下实现Eq。


trait Eq {
    fn equals(self, b: Self) -> bool;
}

trait Ord: Eq {
    fn gte(self, b: Self) -> bool;
}

impl Ord for u64 {
    fn gte(self, b: Self) -> bool {
        // As `Eq` is a supertrait of `Ord`, `Ord` can access the equals method
        self.equals(b) || self.gt(b)
    }
}

To require a supertrait, add a : after the trait name and then list the traits you would like to require and separate them with a +.

若需要超级特征,请在特征名称后添加一个:,然后列出您想要需要的特征并用+将它们分开。

ABI 超特征 (ABI supertraits)

ABIs can also have supertrait annotations:

ABI 也可以有超特征注解:

contract;

trait ABIsupertrait {
    fn foo();
}

abi MyAbi : ABIsupertrait {
    fn bar();
} {
    fn baz() {
        Self::foo() // supertrait method usage
    }
}

impl ABIsupertrait for Contract {
    fn foo() {}
}

// The implementation of MyAbi for Contract must also implement ABIsupertrait
impl MyAbi for Contract {
    fn bar() {
        Self::foo() // supertrait method usage
    }
}

The implementation of MyAbi for Contract must also implement the ABIsupertrait trait. Methods in ABIsupertrait are not available externally, i.e. they're not actually contract methods, but they can be used in the actual contract methods, as shown in the example above.

Contract 的 MyAbi 的实现也必须实现 ABIsupertrait 特征。 ABIsupertrait 中的方法在外部不可用,即它们实际上不是契约方法,但它们可以在实际契约方法中使用,如上例所示。

ABI supertraits are intended to make contract implementations compositional, allowing combining orthogonal contract features using, for instance, libraries.

ABI 超特征旨在使合约实现组合,允许使用库来组合正交合约功能。

相关条目 (Associated Items)

Traits can declare different kinds of associated items in their interface surface: 特征可以在其接口表面声明不同种类的关联项:

关联函数(Associated functions)

Associated functions in traits consist of just function signatures. This indicates that each implementation of the trait for a given type must define all the trait functions.

特征中的关联函数仅由函数签名组成。这表明给定类型的特征的每个实现,都必须定义所有特征函数。

trait Trait {
    fn associated_fn(self, b: Self) -> bool;
}

关联常数(Associated constants)

Associated constants are constants associated with a type.

关联常数是与类型关联的常数。

trait Trait {
    const ID: u32 = 0;
}
trait Trait {
    const ID: u32;
}

用例 (Use Cases)

自定义类型(结构、枚举)- Custom Types (structs, enums)

Often, libraries and APIs have interfaces that are abstracted over a type that implements a certain trait. It is up to the consumer of the interface to implement that trait for the type they wish to use with the interface. For example, let's take a look at a trait and an interface built off of it.

通常,库和 API 具有在实现特定特征类型上抽象的接口。由接口的使用者为其希望与接口一起使用的类型来实现该特征。例如,让我们看一下一个特征和基于其构建的接口。

library;

pub enum Suit {
    Hearts: (),
    Diamonds: (),
    Clubs: (),
    Spades: (),
}

pub trait Card {
    fn suit(self) -> Suit;
    fn value(self) -> u8;
}

fn play_game_with_deck<T>(a: Vec<T>) where T: Card {
    // insert some creative card game here
}

Now, if you want to use the function play_game_with_deck with your struct, you must implement Card for your struct. Note that the following code example assumes a dependency games has been included in the Forc.toml file.

现在,如果你想在你的结构中使用函数play_game_with_deck,您必须为您的结构实现Card。请注意,以下代码示例假定依赖项 games 已包含在 Forc.toml 文件中。

script;

use games::*;

struct MyCard {
    suit: Suit,
    value: u8
}

impl Card for MyCard {
    fn suit(self) -> Suit {
        self.suit
    }
    fn value(self) -> u8 {
        self.value
    }
}

fn main() {
    let mut i = 52;
    let mut deck: Vec<MyCard> = Vec::with_capacity(50);
    while i > 0 {
        i = i - 1;
        deck.push(MyCard { suit: generate_random_suit(), value: i % 4}
    }
    play_game_with_deck(deck);
}

fn generate_random_suit() -> Suit {
  [ ... ]
}
Previous6.2 通用类型 (Generic Types)Next6.4 集 (Assembly)

Last updated 1 year ago

The initializer expression of an in a trait definition may be omitted to indicate that each implementation of the trait for a given type must specify an initializer:

特征定义中 的初始化表达式可以省略,进而指示每个实现给定类型的 trait 必须指定一个初始值设定项:

Check the associated consts section on page.

检查 页面上的关联常数部分。

Note Trait constraints (i.e. using the where keyword) 注意 特征约束(即使用 where 关键字)

函数 Functions
常数 Constants
associated constants
关联常数
constants
常数
have not yet been implemented
尚未实施