Modificadores de clase
Palabras clave modificadoras para declaraciones de clases para controlar el acceso a librerías externas.
Los modificadores de clases controlan cómo se puede usar una clase o mixin, tanto desde dentro de su propia librería como desde fuera de la librería donde se define.
Las palabras clave modificadoras van antes de la declaración de una clase o mixin.
Por ejemplo, escribir abstract class define una clase abstracta.
El conjunto completo de modificadores que pueden aparecer antes de la declaración de una clase incluye:
abstractbasefinalinterfacesealedmixin
Solo el modificador base puede aparecer antes de la declaración de un mixin.
Los modificadores no se aplican a otras declaraciones como
enum, typedef, extension o extension type.
Al decidir si usar modificadores de clase, considera los usos previstos de la clase y de qué comportamientos necesita la clase poder depender.
Sin modificador
#Para permitir el permiso irrestricto para construir o subtipar desde cualquier librería,
usa una declaración class o mixin sin modificador. Por defecto, puedes:
- Construir nuevas instancias de una clase.
- Extender una clase para crear un nuevo subtipo.
- Implementar la interfaz de una clase o mixin.
- Mezclar (Mix in) un mixin o una clase mixin.
abstract
#
Para definir una clase que no requiera una implementación concreta y completa de
toda su interfaz, utiliza el modificador abstract.
Las clases abstractas no se pueden construir desde ninguna librería, ya sea la propia o una librería externa. Las clases abstractas a menudo tienen métodos abstractos.
abstract class Vehicle {
void moveForward(int meters);
}
import 'a.dart';
// Error: `Vehicle` can't be instantiated because
// it is marked as `abstract`.
Vehicle myVehicle = Vehicle();
// Can be extended.
class Car extends Vehicle {
int passengers = 4;
@override
void moveForward(int meters) {
// ...
}
}
// Can be implemented.
class MockVehicle implements Vehicle {
@override
void moveForward(int meters) {
// ...
}
}
Si deseas que tu clase abstracta parezca instanciable, define un constructor factory.
base
#
Para imponer la herencia de la implementación de una clase o mixin,
utiliza el modificador base.
Una clase base no permite la implementación fuera de su propia librería.
Esto garantiza:
- El constructor de la clase base se llama cada vez que se crea una instancia de un subtipo de la clase.
- Todos los miembros privados implementados existen en los subtipos.
-
A new implemented member in a
baseclass does not break subtypes, since all subtypes inherit the new member.- Esto es cierto a menos que el subtipo ya declare un miembro con el mismo nombre y una firma incompatible.
Debes marcar cualquier clase que implemente o extienda una clase base como
base, final o sealed. Esto evita que las librerías externas
rompan las garantías de la clase base.
base class Vehicle {
void moveForward(int meters) {
// ...
}
}
import 'a.dart';
// Can be constructed.
Vehicle myVehicle = Vehicle();
// Can be extended.
base class Car extends Vehicle {
int passengers = 4;
// ...
}
// ERROR: `Vehicle` can't be implemented in a different library because
// it is marked with `base`.
base class MockVehicle implements Vehicle {
@override
void moveForward() {
// ...
}
}
interface
#
Para definir una interfaz, utiliza el modificador interface.
Las librerías fuera de la propia librería definidora de la interfaz pueden
implementar la interfaz, pero no extenderla.
Esto garantiza:
- Cuando uno de los métodos de instancia de la clase llama a
otro método de instancia sobre
this, siempre invocará una implementación conocida del método de la misma librería. - Otras librerías no pueden sobrescribir métodos que los propios métodos de la clase interfaz podrían llamar más tarde de formas inesperadas. Esto reduce el problema de la clase base frágil (fragile base class problem).
interface class Vehicle {
void moveForward(int meters) {
// ...
}
}
import 'a.dart';
// Can be constructed.
Vehicle myVehicle = Vehicle();
// ERROR: `Vehicle` can't be extended in a different library because
// it is marked with `interface`.
class Car extends Vehicle {
int passengers = 4;
// ...
}
// Can be implemented.
class MockVehicle implements Vehicle {
@override
void moveForward(int meters) {
// ...
}
}
abstract interface
#
El uso más común del modificador interface es definir una interfaz pura.
Combina los modificadores interface y abstract
para obtener una clase de interfaz abstracta (abstract interface class).
Al igual que una clase interface, otras librerías pueden
implementar, pero no pueden heredar, una interfaz pura.
Al igual que una clase abstract, una interfaz pura puede tener miembros abstractos.
final
#
Para cerrar la jerarquía de tipos, utiliza el modificador final.
Esto evita la creación de subtipos a partir de una clase fuera de la librería actual.
Desautorizar tanto la herencia como la implementación evita la creación de subtipos por completo.
Esto garantiza:
- Puedes agregar cambios incrementales de forma segura a la API.
- Puedes llamar a los métodos de instancia sabiendo que no han sido sobrescritos en una subclase de terceros.
Las clases final se pueden extender o implementar dentro de la misma librería.
El modificador final engloba los efectos de base, y
por lo tanto cualquier subclase también debe ser marcada como base, final o
sealed.
final class Vehicle {
void moveForward(int meters) {
// ...
}
}
import 'a.dart';
// Can be constructed.
Vehicle myVehicle = Vehicle();
// ERROR: `Vehicle` can't be extended in a different library
// because it is marked `final`.
class Car extends Vehicle {
int passengers = 4;
// ...
}
// ERROR: `Vehicle` can't be implemented in a different library because
// it is marked `final`.
class MockVehicle implements Vehicle {
@override
void moveForward(int meters) {
// ...
}
}
sealed
#
Para crear un conjunto conocido y enumerable de subtipos, utiliza el modificador sealed.
Esto te permite realizar un switch sobre esos subtipos que
está estáticamente garantizado como exhaustivo (exhaustive).
El modificador sealed evita que una clase sea extendida o
implementada fuera de su propia librería. Las clases selladas (sealed) son implícitamente
abstract.
- No se pueden construir a sí mismas.
- Pueden tener constructores factory.
- Pueden definir constructores para que sus subclases los utilicen.
Sin embargo, las subclases de clases selladas no son implícitamente abstractas.
El compilador es consciente de cualquier posible subtipo directo porque solo pueden existir en la misma librería. Esto le permite al compilador alertarte cuando un switch no maneja exhaustivamente todos los subtipos posibles en sus casos:
sealed class Vehicle {}
class Car extends Vehicle {}
class Truck implements Vehicle {}
class Bicycle extends Vehicle {}
// ERROR: `Vehicle` can't be instantiated because
// it is marked `sealed` and therefore, implicitly abstract.
Vehicle myVehicle = Vehicle();
// Subclasses of a sealed class can be instantiated unless also restricted.
Vehicle myCar = Car();
extension VehicleSounds on Vehicle {
String get sound {
// ERROR: The switch does not exhaustively account for
// all possible objects of type `Vehicle`.
// In this example, a `Vehicle` with a run-time type of `Bicycle`
// would not match any of the cases.
return switch (this) {
Car() => 'vroom',
Truck() => 'VROOOOMM',
};
}
}
Si no deseas un cambio exhaustivo (exhaustive switching),
o deseas poder agregar subtipos más adelante sin romper la API,
utiliza el modificador final. Para una comparación más detallada,
lee sealed frente a final.
Combinación de modificadores
#Puedes combinar algunos modificadores para obtener restricciones por capas. La declaración de una clase puede ser, en orden:
- (Opcional)
abstract, que describe si la clase puede contener miembros abstractos y evita la instanciación. - (Opcional) Uno de
base,interface,finalosealed, que describe las restricciones sobre otras librerías que subtipean la clase. - (Opcional)
mixin, que describe si la declaración se puede mezclar (mixed in). - La palabra clave
classen sí misma.
No se pueden combinar algunos modificadores porque son contradictorios, redundantes o mutuamente excluyentes:
abstractconsealed. Una clase sealed es implícitamente abstract.interface,finalosealedconmixin. Estos modificadores de acceso evitan que se mezclen (mixing in).
Para obtener más orientación sobre cómo se pueden combinar los modificadores de clases, consulta la Referencia de modificadores de clases.
A menos que se indique lo contrario, la documentación en este sitio refleja Dart 3.12.2. Página actualizada por última vez el 2026-05-12. Ver fuente oreportar un problema.