Este apartado é de ampliación e consulta. Non necesitas dominar estas ferramentas para empezar con Flutter. Queda coa idea de para que serven e volve aquí cando aparezan nun exemplo.
🧩 Compartir un comportamento con mixin e with
Un mixin permite reutilizar métodos e atributos en varias clases. Definímolo con mixin e engadímolo a unha clase con with.
Non creamos un obxecto do mixin directamente. Usamos os seus métodos nos obxectos das clases que o incorporan.
🧪 Exemplo completo: enviar avisos
Un profesor e un curso poden enviar avisos. Compartimos ese comportamento sen facer que un curso herde de profesor.
🔗 Ver o código en DartPad — https://dartpad.dev/?id=0ff6645e6a8134e9b4459f7b975c7788
Podemos combinar unha superclase e mixins: class A extends B with C, D. Primeiro escribimos extends e despois with. Se varios mixins ofrecen o mesmo método, ten prioridade o último da lista, salvo que a clase o sobrescriba.
📱 Nas animacións de Flutter veremos
with SingleTickerProviderStateMixin. Polo de agora chega con recoñecer que engade un comportamento á clase; o seu uso concreto explicarémolo alí.
Ademais de with, existen restricións con on e declaracións como mixin class ou base mixin. Permiten controlar como se reutiliza o comportamento. Para empezar abonda co exemplo de avisos.
🔗 Mixins na documentación de Dart — https://dart.dev/language/mixins
🏭 Construtores factory
Un factory executa código para obter o obxecto que devolverá. Pode crear un obxecto chamando a outro construtor, reutilizar un existente ou devolver un subtipo. Non ten acceso a this.
Atoparalo en exemplos que converten mapas en obxectos. Non é necesario usalo sempre para iso; aquí amosamos unha forma habitual.
class Profesor {
final String nome;
Profesor({required this.nome});
// Recibimos un mapa e devolvemos un obxecto Profesor.
factory Profesor.fromMap(Map<String, String> datos) {
final nome = datos['nome'];
if (nome == null || nome.trim().isEmpty) {
throw ArgumentError('Falta o nome do profesor.');
}
return Profesor(nome: nome.trim());
}
}
void main() {
var profesor = Profesor.fromMap({'nome': 'Diego Rodicio'});
print(profesor.nome);
}
fromMap e fromJson son nomes escollidos por convención, non palabras reservadas. Cando usemos estes exemplos en Flutter, revisaremos que datos reciben e que obxecto devolven.
🔗 Construtores factory — https://dart.dev/language/constructors#factory-constructors
🔀 Construtores de redirección
Delegan a inicialización noutro construtor. Evitan repetir as mesmas asignacións.
class Profesor {
final String nome;
Profesor(this.nome);
// this(...) chama ao outro construtor da mesma clase.
Profesor.senDatos() : this('Sen asignar');
}
void main() {
print(Profesor.senDatos().nome);
}
A chamada crea un obxecto, non dous. Esta forma de redirección non leva corpo de construtor.
🔗 Construtores de redirección — https://dart.dev/language/constructors#redirecting-constructors
🧊 Un detalle de const: instancias compartidas
Dúas expresións constantes equivalentes poden referirse á mesma instancia. identical(a, b) comproba se dúas referencias corresponden ao mesmo obxecto; a == b usa a comparación de igualdade dese tipo. Non necesitamos controlar isto para escribir os primeiros widgets.
🔗 Uso de construtores e obxectos constantes — https://dart.dev/language/classes#using-constructors
🧰 Métodos de extensión
Permiten engadir operacións que se usan como métodos dun tipo existente, sen modificar a súa clase nin crear unha subclase.
extension TextoSaudo on String {
// this é a cadea sobre a que se chama o método.
String saudar() => 'Ola, $this!';
}
void main() {
print('Diego Rodicio'.saudar());
}
Resólvense segundo o tipo coñecido ao compilar. Se a extensión está noutra biblioteca, debemos importala para usala.
🔗 Métodos de extensión — https://dart.dev/language/extension-methods
🏷️ Tipos de extensión
Un extension type crea unha interface distinta sobre un valor existente. Por exemplo, permite tratar un enteiro como un identificador. Non crea un obxecto adicional que envolva ese valor; a distinción é estática. Os seus métodos si executan código.
É unha ferramenta avanzada, dispoñible desde Dart 3.3. Non a necesitamos nos primeiros exemplos de Flutter.
🔗 Tipos de extensión — https://dart.dev/language/extension-types
🔒 Modificadores avanzados de clases
🧠 Ampliación: estes modificadores axudan a deseñar clases que vai usar outro código. Non fai falta memorizar todas as combinacións agora.
📚 Primeiro: a biblioteca
Normalmente, cada ficheiro .dart é unha biblioteca distinta. Importar un ficheiro non une as dúas bibliotecas. Tamén se poden repartir bibliotecas con part, pero non o necesitamos aquí.
📋 Que permite cada modificador?
As restricións desta táboa refírense ao código de outra biblioteca.
| Modificador | Para que serve? |
|---|---|
base | Permite herdar con extends, pero non implementar con implements desde fóra. |
interface | Permite implementar desde fóra, pero non herdar a implementación con extends. |
final | Impide estender e implementar desde fóra. Non fai inmutables os atributos. |
sealed | Limita os subtipos directos á súa biblioteca e permite comprobar casos nun switch. É abstracta automaticamente. |
Dentro da súa biblioteca, estas clases si poden estenderse ou implementarse. Os subtipos dunha clase base ou final deben levar base, final ou sealed, tamén dentro da biblioteca.
interface por si só non permite métodos abstractos: para un contrato sen implementación úsase habitualmente abstract interface class. Xa vimos un contrato sinxelo con abstract class e implements en Herdanza.
📌 Non se poden combinar palabras libremente:
base final class,abstract sealed classoufinal mixinnon son válidos. Consulta a táboa oficial cando o necesites.🔗 Modificadores de clases — https://dart.dev/language/class-modifiers · Combinacións válidas — https://dart.dev/language/modifier-reference
🧪 Exemplo de consulta en DartPad
Reúne os modificadores nun único programa comentado. Todo está no mesmo ficheiro: os comentarios explican que cambiaría ao separar as clases noutra biblioteca. Non é necesario estudar este bloque de memoria.
🔗 Ver o código en DartPad — https://dartpad.dev/?id=708e3bd2dd63773aaf5967988632e15b