Dart: OOP, Mixins and Inheritance

Classes, named constructors, mixins (with) and getters/setters with validation

🐾 Demo: Animal Hierarchy

Object created:

runtimeType
Duck (con mixin PuedeNadar)
descripcion (getter)
Rex is 3 years old
hacerSonido()
Quack quack
nadar() — comes from the mixin
splashing in the water 🌊

Create your animal

class Animal {
  final String nombre;
  int _edad;

  Animal(this.nombre, this._edad);

  // Constructor con nombre: delega en el constructor principal  Animal.bebe(String nombre) : this(nombre, 0);

  String get descripcion => '$nombre tiene $_edad años';

  set actualizarEdad(int nuevaEdad) {
    if (nuevaEdad < 0) {
      throw ArgumentError(t('La edad no puede ser negativa'));
    }
    _edad = nuevaEdad;
  }

  String hacerSonido() => '...';
}

mixin PuedeNadar {
  String nadar() => 'chapoteando en el agua';
}

class Pato extends Animal with PuedeNadar {
  Pato(String nombre, int edad) : super(nombre, edad);

  @override
  String hacerSonido() => 'Cuac cuac';
}
💡 with (mixin) vs extends (herencia)

With extends a class can only inherit from ONE parent class. With with NombreMixin you can "mix" behavior from several mixins at once — that's why Pato can inherit from Animal AND also gain nadar() without Perro or Gato having it.

📖 Factory Constructor (singleton pattern)

class ConfiguracionApp {
  static final ConfiguracionApp _instancia = ConfiguracionApp._interno();

  // El constructor normal está "oculto" (empieza por _)  ConfiguracionApp._interno();

  // El factory decide qué instancia devolver — aquí, siempre la misma  factory ConfiguracionApp() {
    return _instancia;
  }
}

final config1 = ConfiguracionApp();
final config2 = ConfiguracionApp();
print(identical(config1, config2)); // true: son el mismo objeto
💡 ¿Para qué sirve factory?

A factory constructor doesn't have to create a new object every time: it can return an already-existing instance (singleton), return a different subclass depending on the parameters, or build the object from a JSON validating data first.

🎯 Key Concepts

Constructors

  • Normal: Animal(this.nombre)
  • Named: Animal.bebe(...)
  • factory: decides what to return

Mixins

  • mixin + with
  • Reuses behavior without single inheritance

Getters / Setters

  • get calculates a value when read
  • set can validate when writing

💪 Practical Exercise

Extend the hierarchy

  1. Create a mixin PuedeVolar with a method volar() and apply it also to a new class Paloma extends Animal.
  2. Add a getter esAdulto that returns true if the age is greater than or equal to 2.
  3. Create a constructor factory Animal.desdeTexto(String csv) that receives "nombre,edad" and builds the object by parsing the text.

Solution 1

mixin PuedeVolar {
  String volar() => 'volando por el cielo';
}

class Paloma extends Animal with PuedeVolar {
  Paloma(String nombre, int edad) : super(nombre, edad);
}

Solution 2

bool get esAdulto => _edad >= 2;

Solution 3

factory Animal.desdeTexto(String csv) {
  final partes = csv.split(',');
  return Animal(partes[0], int.parse(partes[1]));
}