Appendix C: Derivable Traits
En varias partes del libro, hemos discutido el atributo derive
, que puedes aplicar a una definición struct o enum. El atributo derive
genera código para implementar un trait por defecto en el tipo que has anotado con la sintaxis derive
.
En este apéndice, proporcionamos una referencia completa que detalla todos los traits de la biblioteca estándar compatibles con el atributo derive
.
Estos traits listados aquí son los únicos definidos por la librería principal que pueden ser implementados en tus tipos usando derive
. Otros traits definidos en la biblioteca estándar no tienen un comportamiento sensible por defecto, por lo que depende de ti implementarlos de la manera que tenga sentido para lo que estás tratando de lograr.
La lista de traits derivables proporcionada en este apéndice no abarca todas las posibilidades: las bibliotecas externas pueden implementar derive
para sus propios rasgos, ampliando la lista de rasgos compatibles con derive
.
PartialEq for equality comparison
El trait PartialEq
permite la comparación entre instancias de un tipo por igualdad, habilitando así los operadores == y !=.
Cuando PartialEq
se deriva en structs, dos instancias son iguales sólo si todos los campos son iguales, y las instancias no son iguales si algún campo no lo es. Cuando se deriva en enums, cada variante es igual a sí misma y no a las demás variantes.
Ejemplo:
#[derive(PartialEq, Drop)] struct A { item: felt252 } fn main() { let first_struct = A { item: 2 }; let second_struct = A { item: 2 }; assert(first_struct == second_struct, 'Structs are different'); }
Clone and Copy for Duplicating Values
El trait Clone
proporciona la funcionalidad de crear explícitamente una copia profunda de un valor.
Derivar Clone
implementa el método clone
, que, a su vez, llama a clone en cada uno de los componentes del tipo. Esto significa que todos los campos o valores del tipo también deben implementar Clone
para derivar Clone
.
Ejemplo:
use clone::Clone; #[derive(Clone, Drop)] struct A { item: felt252 } fn main() { let first_struct = A { item: 2 }; let second_struct = first_struct.clone(); assert(second_struct.item == 2, 'Not equal'); }
El trait Copy
permite la duplicación de valores. Puedes derivar Copy
de cualquier tipo cuyas partes implementen Copy
.
Ejemplo:
#[derive(Copy, Drop)] struct A { item: felt252 } fn main() { let first_struct = A { item: 2 }; let second_struct = first_struct; assert(second_struct.item == 2, 'Not equal'); assert(first_struct.item == 2, 'Not Equal'); // Copy Trait prevents firs_struct from moving into second_struct }
Serializing with Serde
Serde
proporciona implementaciones trait para las funciones serialize
y deserialize
para estructuras de datos definidas en tu crate. Te permite transformar tu estructura en un array (o lo contrario).
Ejemplo:
use serde::Serde; use array::ArrayTrait; #[derive(Serde, Drop)] struct A { item_one: felt252, item_two: felt252, } fn main() { let first_struct = A { item_one: 2, item_two: 99, }; let mut output_array = ArrayTrait::new(); let serialized = first_struct.serialize(ref output_array); panic(output_array); }
Output:
Run panicked with [2 (''), 99 ('c'), ].
Podemos ver aquí que nuestra estructura A ha sido serializada en el array de salida.
Además, podemos utilizar la función deserialize
para convertir el array serializado de nuevo en nuestra estructura A.
Ejemplo:
use serde::Serde; use array::ArrayTrait; use option::OptionTrait; #[derive(Serde, Drop)] struct A { item_one: felt252, item_two: felt252, } fn main() { let first_struct = A { item_one: 2, item_two: 99, }; let mut output_array = ArrayTrait::new(); let mut serialized = first_struct.serialize(ref output_array); let mut span_array = output_array.span(); let deserialized_struct: A = Serde::<A>::deserialize(ref span_array).unwrap(); }
Aquí estamos convirtiendo un array span serializado de nuevo a la estructura A. deserialize
devuelve una Option
por lo que necesitamos desenvolverla. Cuando usamos deserialize también necesitamos especificar el tipo al que queremos deserializar.
Drop and Destruct
When moving out of scope, variables need to be moved first. This is where the Drop
trait intervenes. You can find more details about its usage here.
Moreover Dictionary need to be squashed before going out of scope. Calling manually the squash
method on each of them can be quickly redundant. Destruct
trait allows Dictionaries to be automatically squashed when they get out of scope. You can also find more information about Destruct
here.
Store
Storing a user-defined struct in a storage variable within a Starknet contract requires the Store
trait to be implemented for this type. You can automatically derive the store
trait for all structs that do not contain complex types like Dictionaries or Arrays.
Ejemplo:
#[starknet::contract]
mod contract {
#[derive(Drop, starknet::Store)]
struct A {
item_one: felt252,
item_two: felt252,
}
#[storage]
struct Storage {
my_storage: A,
}
}
Here we demonstrate the implementation of a struct A
that derives the Store trait. This struct A
is subsequently used
as a storage variable in the contract.
PartialOrd and Ord for Ordering Comparisons
In addition to the PartialEq
trait, the standard library also provides the PartialOrd
and Ord
traits to compare values for ordering.
The PartialOrd
trait allows for comparison between instances of a type for ordering, thereby enabling the <, <=, >, and >= operators.
When PartialOrd
is derived on structs, two instances are ordered by comparing each field in turn.