Uses y Aliases
La sintaxis use
puede usarse para crear aliases a miembros en otros módulos. use
puede usarse para crear aliases que duren ya sea para todo el módulo, o para un ámbito de bloque de expresión dado.
Sintaxis
Sección titulada «Sintaxis»Hay varios casos de sintaxis diferentes para use
. Comenzando con el más simple, tenemos lo siguiente para crear aliases a otros módulos:
use <address>::<module name>;use <address>::<module name> as <module alias name>;
Por ejemplo:
script { use std::vector; use std::vector as V;}
use std::vector;
introduce un alias vector
para std::vector
. Esto significa que en cualquier lugar donde quieras usar el nombre del módulo std::vector
(asumiendo que este use
está en ámbito), podrías usar vector
en su lugar. use std::vector;
es equivalente a use std::vector as vector;
De manera similar, use std::vector as V;
te permitiría usar V
en lugar de std::vector
module 0x42::example { use std::vector; use std::vector as V;
fun new_vecs(): (vector<u8>, vector<u8>, vector<u8>) { let v1 = std::vector::empty(); let v2 = vector::empty(); let v3 = V::empty(); (v1, v2, v3) }}
Si quieres importar un miembro específico del módulo (como una función, struct, o constante), puedes usar la siguiente sintaxis:
use <address>::<module name>::<module member>;use <address>::<module name>::<module member> as <member alias>;
Por ejemplo:
script { use std::vector::empty; use std::vector::empty as empty_vec;}
Esto te permitiría usar la función std::vector::empty
sin calificación completa. En su lugar, podrías usar empty
y empty_vec
respectivamente. Nuevamente, use std::vector::empty;
es equivalente a use std::vector::empty as empty;
module 0x42::example { use std::vector::empty; use std::vector::empty as empty_vec;
fun new_vecs(): (vector<u8>, vector<u8>, vector<u8>) { let v1 = std::vector::empty(); let v2 = empty(); let v3 = empty_vec(); (v1, v2, v3) }}
Si quieres agregar aliases para múltiples miembros del módulo a la vez, puedes hacerlo con la siguiente sintaxis:
use <address>::<module name>::{<module member>, <module member> as <member alias> ... };
Por ejemplo:
module 0x42::example { use std::vector::{push_back, length as len, pop_back};
fun swap_last_two<T>(v: &mut vector<T>) { assert!(len(v) >= 2, 42); let last = pop_back(v); let second_to_last = pop_back(v); push_back(v, last); push_back(v, second_to_last) }}
Si quieres importar tanto el módulo como algunos de sus miembros, puedes usar Self
. Self
es un alias para el módulo:
module 0x42::example { use std::vector::{Self, empty};
fun new_vec(): vector<u8> { let v1 = vector::empty(); // Equivalente a std::vector::empty() let v2 = Self::empty(); // Equivalente a std::vector::empty() let v3 = empty(); // Equivalente a std::vector::empty() v1 }}
Para importar todas las funciones públicas de un módulo, puedes usar el patrón comodín *
:
module 0x42::example { use std::vector::*;
fun example(): vector<u64> { let v = empty(); // std::vector::empty() push_back(&mut v, 1); push_back(&mut v, 2); v }}
Importación de Múltiples Módulos
Sección titulada «Importación de Múltiples Módulos»Puedes importar múltiples módulos en una sola declaración:
module 0x42::example { use std::{vector, option, string};
fun example() { let v = vector::empty<u64>(); let opt = option::some(42); let s = string::utf8(b"hello"); }}
Dentro de Expresiones
Sección titulada «Dentro de Expresiones»Puedes introducir use
localmente dentro de expresiones. Esto es útil cuando solo necesitas el alias por un corto período:
module 0x42::example { fun example(): vector<u8> { { use std::vector::{empty, push_back}; let v = empty(); push_back(&mut v, 1); push_back(&mut v, 2); v } // empty y push_back ya no están en ámbito aquí }}
Resolución de Nombres
Sección titulada «Resolución de Nombres»Los use
se resuelven en el orden que aparecen. Si hay un conflicto de nombres, la declaración posterior toma precedencia:
module 0x42::example { use std::vector; use std::option as vector; // Ahora 'vector' se refiere a std::option
fun example() { let opt = vector::some(42); // Esto usa std::option::some() // let v = vector::empty(); // Esto NO funcionaría }}
Aliases con Structs
Sección titulada «Aliases con Structs»Puedes crear aliases para structs:
module 0x42::example { use std::string::String; use std::option::Option;
struct User { name: String, email: Option<String>, }
fun create_user(name: String): User { User { name, email: Option::none(), } }}
Aliases con Constantes
Sección titulada «Aliases con Constantes»También puedes importar constantes:
module 0x42::example { use std::error::{INVALID_ARGUMENT, NOT_FOUND};
const E_CUSTOM_ERROR: u64 = 100;
fun validate_input(x: u64) { assert!(x > 0, INVALID_ARGUMENT); assert!(x < 1000, NOT_FOUND); }}
Patrones de Uso Comunes
Sección titulada «Patrones de Uso Comunes»Importación de Módulos de Utilidad
Sección titulada «Importación de Módulos de Utilidad»module 0x42::my_app { use std::{ vector, option::{Self, Option}, string::{Self, String}, error, };
struct Config { name: String, features: vector<String>, debug_mode: Option<bool>, }
fun create_config(name: String): Config { Config { name, features: vector::empty(), debug_mode: option::some(false), } }}
Importación de Funciones Frecuentemente Usadas
Sección titulada «Importación de Funciones Frecuentemente Usadas»module 0x42::math_utils { use std::vector::{push_back, pop_back, length, is_empty};
fun process_numbers(numbers: &mut vector<u64>) { if (is_empty(numbers)) { push_back(numbers, 0); };
while (length(numbers) > 10) { pop_back(numbers); }; }}
Aliases para Módulos con Nombres Largos
Sección titulada «Aliases para Módulos con Nombres Largos»module 0x42::example { use my_very_long_module_name::some_nested_module as short;
fun example() { short::do_something(); short::helper_function(); }}
Buenas Prácticas
Sección titulada «Buenas Prácticas»1. Agrupa Imports Relacionados
Sección titulada «1. Agrupa Imports Relacionados»// ✅ Bueno - imports agrupados lógicamentemodule 0x42::token { // Bibliotecas estándar use std::{ vector, option::{Self, Option}, string::String, };
// Bibliotecas de Aptos use aptos_framework::{ coin, event, timestamp, };
// Módulos locales use 0x42::{ permissions, events, };}
2. Usa Aliases Descriptivos
Sección titulada «2. Usa Aliases Descriptivos»// ✅ Bueno - aliases clarosmodule 0x42::exchange { use std::string::String; use aptos_framework::coin::{Self as coin_utils}; use 0x42::trading::order_book as book;
fun create_order() { book::add_order(/* ... */); coin_utils::transfer(/* ... */); }}
// ❌ Malo - aliases confusosmodule 0x42::exchange { use std::string::String as S; use aptos_framework::coin as c; use 0x42::trading::order_book as ob;}
3. Evita Imports Excesivos
Sección titulada «3. Evita Imports Excesivos»// ❌ Malo - demasiados imports específicosmodule 0x42::bad_example { use std::vector::{ empty, push_back, pop_back, length, is_empty, borrow, borrow_mut, contains, index_of, remove, reverse, append, split_off, insert };}
// ✅ Mejor - import del módulo con funciones más usadas específicamentemodule 0x42::good_example { use std::vector::{Self, push_back, pop_back, length};
fun example() { let v = vector::empty(); // Usar el módulo para funciones menos frecuentes push_back(&mut v, 1); // Usar import directo para funciones frecuentes }}
4. Ordena los Imports
Sección titulada «4. Ordena los Imports»// ✅ Bueno - orden consistentemodule 0x42::ordered_imports { // 1. Bibliotecas estándar (alfabéticamente) use std::option; use std::string; use std::vector;
// 2. Bibliotecas de framework (alfabéticamente) use aptos_framework::coin; use aptos_framework::event;
// 3. Módulos de terceros (alfabéticamente) use some_package::utilities;
// 4. Módulos locales (alfabéticamente) use 0x42::helpers; use 0x42::types;}
Ámbito y Visibilidad
Sección titulada «Ámbito y Visibilidad»Ámbito del Módulo vs Ámbito Local
Sección titulada «Ámbito del Módulo vs Ámbito Local»module 0x42::scope_example { use std::vector; // Ámbito del módulo - disponible en todas las funciones
fun module_scope_example() { vector::empty<u64>(); // Funciona - 'vector' está en ámbito del módulo }
fun local_scope_example() { { use std::option; // Ámbito local - solo dentro de este bloque option::some(42); }; // 'option' sale del ámbito aquí
// option::none(); // Error - 'option' no está en ámbito vector::empty<u64>(); // Funciona - 'vector' todavía está en ámbito }}
Shadowing (Sombreado)
Sección titulada «Shadowing (Sombreado)»module 0x42::shadowing { use std::vector;
fun shadowing_example() { let v1 = vector::empty<u64>(); // Usa std::vector
{ use std::option as vector; // Sombrea el import anterior let opt = vector::some(42); // Usa std::option // let v2 = vector::empty<u64>(); // Error - 'vector' ahora es std::option };
let v3 = vector::empty<u64>(); // Usa std::vector nuevamente }}
Casos de Uso Avanzados
Sección titulada «Casos de Uso Avanzados»Imports Condicionales por Características
Sección titulada «Imports Condicionales por Características»module 0x42::feature_imports { #[cfg(feature = "testing")] use std::debug;
#[cfg(feature = "production")] use aptos_framework::event;
fun conditional_usage() { #[cfg(feature = "testing")] debug::print(&b"Debug message");
#[cfg(feature = "production")] event::emit_event(/* ... */); }}
Re-exports
Sección titulada «Re-exports»module 0x42::re_exports { // Re-exportar funciones comúnmente usadas public use std::vector::{ empty, push_back, pop_back, length, };
public use std::option::{ some, none, is_some, is_none, };}
module 0x42::consumer { use 0x42::re_exports::{empty, push_back, some, none};
fun example() { let v = empty<u64>(); push_back(&mut v, 42); let opt = some(v); }}
Imports para Genéricos
Sección titulada «Imports para Genéricos»module 0x42::generic_imports { use std::vector::{Self as Vec}; use std::option::{Self as Opt, Option};
struct Container<T> { items: Vec<T>, default: Option<T>, }
fun new_container<T>(): Container<T> { Container { items: Vec::empty(), default: Opt::none(), } }}
Resolución de Problemas
Sección titulada «Resolución de Problemas»Error: Nombre No Encontrado
Sección titulada «Error: Nombre No Encontrado»// ❌ Error - import faltantemodule 0x42::error_example { fun example() { let v = vector::empty(); // Error: 'vector' no está en ámbito }}
// ✅ Solución - agregar importmodule 0x42::fixed_example { use std::vector;
fun example() { let v = vector::empty(); // OK }}
Error: Import Ambiguo
Sección titulada «Error: Import Ambiguo»// ❌ Error - imports ambiguosmodule 0x42::ambiguous { use std::vector::empty; use std::option::none as empty; // Conflicto con el import anterior
fun example() { let v = empty(); // Error: ¿cuál 'empty'? }}
// ✅ Solución - usar aliases únicosmodule 0x42::unambiguous { use std::vector::empty as empty_vec; use std::option::none as empty_opt;
fun example() { let v = empty_vec(); // Claro let opt = empty_opt(); // Claro }}
Error: Import Circular
Sección titulada «Error: Import Circular»// ❌ Error potencial - dependencia circularmodule 0x42::module_a { use 0x42::module_b; // ...}
module 0x42::module_b { use 0x42::module_a; // Puede causar dependencia circular // ...}
Limitaciones
Sección titulada «Limitaciones»1. No se Pueden Importar Tipos Privados
Sección titulada «1. No se Pueden Importar Tipos Privados»module 0x42::private_types { struct PrivateStruct { value: u64 } // No tiene 'public'
public fun get_private(): PrivateStruct { PrivateStruct { value: 42 } }}
module 0x42::consumer { // Error: no se puede importar tipo privado // use 0x42::private_types::PrivateStruct;
use 0x42::private_types;
fun example() { let s = private_types::get_private(); // OK - función pública // let value = s.value; // Error - campo privado }}
2. No se Pueden Importar Funciones Privadas
Sección titulada «2. No se Pueden Importar Funciones Privadas»module 0x42::private_functions { fun private_helper() { } // No tiene 'public'
public fun public_function() { private_helper(); // OK - dentro del mismo módulo }}
module 0x42::consumer { // Error: no se puede importar función privada // use 0x42::private_functions::private_helper;
use 0x42::private_functions::public_function; // OK}
Conclusión
Sección titulada «Conclusión»El sistema use
de Move proporciona una manera flexible de importar y crear aliases para módulos y sus miembros. Entender cómo usar efectivamente las declaraciones use
puede hacer que tu código sea más legible y mantenible.
Puntos clave para recordar:
- Los
use
pueden importar módulos completos o miembros específicos - Los aliases pueden simplificar nombres largos de módulos
- Los imports locales tienen ámbito limitado a su bloque
- Siempre agrupa y ordena los imports de manera consistente
- Evita conflicts de nombres usando aliases descriptivos
- Solo se pueden importar elementos públicos de otros módulos