DMarlon Studio

Lección 6 · 6 de 20

Mixins · Dart

Reutilice comportamiento en Dart con mixins: with para aplicarlos, on para limitarlos y miembros abstractos que exigen datos a la clase.

Dart · Mixins en DMarlon Studio: el código del ejemplo y su salida en la terminal

Dart solo permite heredar de una clase, pero a menudo varias clases necesitan el mismo trozo de comportamiento sin ser parientes. Un `mixin` es ese trozo reutilizable: campos y métodos que se «mezclan» en una clase con la palabra `with`.

Discountable añade un campo, percentOff, y un getter, finalPrice, que resta el porcentaje con división entera. Con `on Product` se limita a las clases que son Product y, a cambio, puede usar price con toda tranquilidad: el compilador sabe que existirá.

Shippable no tiene restricción y declara weightKg como abstracto: es la clase que lo usa la que debe aportarlo. Con ese dato calcula shippingCost, 399 céntimos hasta un kilo y 699 a partir de ahí. Un mixin puede, por tanto, ofrecer lógica y exigir a cambio los datos que necesita.

Book mezcla los dos (with Discountable, Shippable) y Ebook solo el descuento, porque un libro digital no se envía. En main, la cascada ..percentOff = 20 asigna el campo que aportó el mixin. Los mixins también son tipos, y is los reconoce: un Book es Discountable y además Product, mientras que un Ebook no es Shippable.

Código · main.dart

abstract class Product { String get name; int get price; } // price in cents// A mixin adds fields and methods to any class that uses it.// "on Product" means it can only be mixed into products.mixin Discountable on Product {  int percentOff = 0;  int get finalPrice => price - price * percentOff ~/ 100;}mixin Shippable {  double get weightKg; // the class must provide this  int get shippingCost => weightKg <= 1 ? 399 : 699;}class Book extends Product with Discountable, Shippable {  @override final String name = 'Clean Code';  @override final int price = 3500;  @override final double weightKg = 0.8;}class Ebook extends Product with Discountable {  @override final String name = 'Dart in Action (PDF)';  @override final int price = 1800;}void main() {  final book = Book()..percentOff = 20;  final ebook = Ebook()..percentOff = 50;  print('${book.name}: ${book.finalPrice} + shipping ${book.shippingCost}');  print('${ebook.name}: ${ebook.finalPrice}, ships: ${ebook is Shippable}');  print('A Book is Discountable: ${book is Discountable}, is Product: ${book is Product}');}

Salida · dart run main.dart

Clean Code: 2800 + shipping 399
Dart in Action (PDF): 900, ships: false
A Book is Discountable: true, is Product: true

Para recordar

  • Un mixin reutiliza código en clases que no comparten herencia.
  • Se aplica con with, y se pueden aplicar varios a la vez.
  • on Clase limita dónde se usa y permite usar los miembros de esa clase.
  • Un mixin puede exigir miembros abstractos a la clase que lo usa.
  • Los mixins también son tipos: funcionan con is.

Ejercicio

Cree un mixin Reviewable con una lista de notas y un getter rating que dé la media, aplíquelo a Book y añada dos valoraciones.