Articulo de referencia

Mezclar

En los lenguajes de programación orientados a objetos , un mixin (o mix-in ) [ 1 ] [ 2 ] [ 3 ] [ 4 ] es una clase que contiene métodos que pueden ser utilizados por otras clases...

En los lenguajes de programación orientados a objetos , un mixin (o mix-in ) [ 1 ] [ 2 ] [ 3 ] [ 4 ] es una clase que contiene métodos que pueden ser utilizados por otras clases sin necesidad de ser la clase padre de dichas clases. La forma en que estas otras clases acceden a los métodos del mixin depende del lenguaje. A veces, se describe a los mixins como "incluidos" en lugar de "heredados".

Los mixins fomentan la reutilización de código y pueden utilizarse para evitar la ambigüedad de herencia que puede causar la herencia múltiple [ 5 ] (el " problema del diamante "), o para sortear la falta de soporte para la herencia múltiple en un lenguaje. Un mixin también puede considerarse una interfaz con métodos implementados . Este patrón es un ejemplo de cómo se aplica el principio de inversión de dependencias .

Historia

Los mixins aparecieron por primera vez en el sistema Flavors orientado a objetos de Symbolics (desarrollado por Howard Cannon), que era un enfoque de la orientación a objetos utilizado en Lisp Machine Lisp . El nombre se inspiró en la heladería Steve's Ice Cream Parlor en Somerville, Massachusetts: [ 1 ] El dueño de la heladería ofrecía un sabor básico de helado (vainilla, chocolate, etc.) y le añadía una combinación de ingredientes adicionales (frutos secos, galletas, dulce de leche, etc.) y llamaba a ese producto " mix-in ", su propio término registrado en ese momento. [ 2 ]

Definición

Los mixins son un concepto del lenguaje que permite a un programador inyectar código en una clase . La programación con mixins es un estilo de desarrollo de software en el que se crean unidades de funcionalidad en una clase y luego se combinan con otras clases. [ 6 ]

Una clase mixin actúa como la clase padre, conteniendo la funcionalidad deseada. Una subclase puede heredar o simplemente reutilizar esta funcionalidad, pero no como un medio de especialización. Normalmente, el mixin exportará la funcionalidad deseada a una clase hija , sin crear una relación rígida y única de "es un". Aquí radica la diferencia importante entre los conceptos de mixins y herencia : la clase hija puede heredar todas las características de la clase padre, pero no es necesario aplicar la semántica de que la hija "sea un tipo de" la padre.

Ventajas

  1. Proporciona un mecanismo para la herencia múltiple al permitir que una clase utilice funcionalidades comunes de múltiples clases, pero sin la semántica compleja de la herencia múltiple. [ 7 ]
  2. Reutilización de código : Los mixins son útiles cuando un programador quiere compartir funcionalidad entre diferentes clases. En lugar de repetir el mismo código una y otra vez, la funcionalidad común se puede agrupar en un mixin y luego incluirla en cada clase que la requiera. [ 8 ]
  3. Los mixins permiten la herencia y el uso de solo las características deseadas de la clase padre, no necesariamente todas las características de la clase padre. [ 9 ]

Implementaciones

En Simula , las clases se definen en un bloque donde se definen conjuntamente los atributos, los métodos y la inicialización de la clase; de ​​este modo, todos los métodos que se pueden invocar en una clase se definen juntos, y la definición de la clase queda completa.

En Flavors , un mixin es una clase de la que otra clase puede heredar definiciones de ranuras y métodos. El mixin generalmente no tiene instancias directas. Dado que un Flavor puede heredar de más de un Flavor, puede heredar de uno o más mixins. Cabe destacar que la versión original de Flavors no utilizaba funciones genéricas.

En New Flavors (sucesor de Flavors) y CLOS , los métodos se organizan en " funciones genéricas ". Estas funciones genéricas son funciones que se definen en múltiples casos (métodos) mediante combinaciones de despacho de clases y métodos.

CLOS y Flavors permiten que los métodos mixin agreguen comportamiento a los métodos existentes: :beforey :afterdaemons, whoppers y wrappers en Flavors. CLOS agregó :aroundmétodos y la capacidad de llamar a métodos sombreados a través de CALL-NEXT-METHOD. Así, por ejemplo, un stream-lock-mixin puede agregar bloqueo alrededor de los métodos existentes de una clase de flujo. En Flavors se escribiría un wrapper o un whopper y en CLOS se usaría un :aroundmétodo. Tanto CLOS como Flavors permiten la reutilización calculada a través de combinaciones de métodos. Los métodos :before, :aftery :aroundson una característica de la combinación de métodos estándar. Se proporcionan otras combinaciones de métodos.

Un ejemplo es la +combinación de métodos, donde los valores resultantes de cada uno de los métodos aplicables de una función genérica se suman aritméticamente para calcular el valor de retorno. Esto se utiliza, por ejemplo, con el mixin de borde para objetos gráficos. Un objeto gráfico puede tener una función de ancho genérica. El mixin de borde agregaría un borde alrededor del objeto y tendría un método para calcular su ancho. Una nueva clase bordered-button(que es a la vez un objeto gráfico y utiliza el bordermixin) calcularía su ancho llamando a todos los métodos de ancho aplicables, mediante la +combinación de métodos. Todos los valores de retorno se suman y crean el ancho combinado del objeto.

En un artículo de OOPSLA 90, [ 10 ] Gilad Bracha y William Cook reinterpretan diferentes mecanismos de herencia encontrados en Smalltalk, Beta y CLOS como formas especiales de herencia de mixin.

Lenguajes de programación que utilizan mixins

Además de Flavors y CLOS (que forma parte de Common Lisp ), algunos lenguajes que utilizan mixins son:

Algunos lenguajes no admiten mixins a nivel de lenguaje, pero pueden imitarlos fácilmente copiando métodos de un objeto a otro en tiempo de ejecución, "tomando prestados" así los métodos del mixin. Esto también es posible con lenguajes de tipado estático , pero requiere construir un nuevo objeto con el conjunto extendido de métodos.

Otros lenguajes que no admiten mixins pueden hacerlo de forma indirecta mediante otras construcciones del lenguaje. Por ejemplo, Visual Basic .NET y C# admiten la adición de métodos de extensión en las interfaces, lo que significa que cualquier clase que implemente una interfaz con métodos de extensión definidos tendrá dichos métodos disponibles como pseudomiembros.

Ejemplos

Lisp común

Common Lisp proporciona mixins en CLOS (Common Lisp Object System) similares a los Flavors.

object-widthEs una función genérica con un argumento que utiliza la +combinación de métodos. Esta combinación determina que se llamarán todos los métodos aplicables a una función genérica y se sumarán los resultados.

( defgeneric object-width ( object ) ( :method-combination + ))

buttones una clase con una ranura para el texto del botón.

( defclass button () (( text :initform "Haz clic aquí" )))

Hay un método para objetos de la clase botón que calcula el ancho en función de la longitud del texto del botón. +es el calificador del método para la combinación de métodos del mismo nombre.

( defmethod object-width + (( object button )) ( * 10 ( length ( slot-value object 'text ))))

Una border-mixinclase. La nomenclatura es solo una convención. No hay superclases ni ranuras.

( defclass border-mixin () ())

Existe un método para calcular el ancho del borde. Aquí es simplemente 4.

( defmethod object-width + (( object border-mixin )) 4 )

bordered-buttones una clase que hereda de border-mixiny button.

( defclass bordered-button ( border-mixin button ) ())

Ahora podemos calcular el ancho de un botón. Llamando a object-widthse calcula 80. El resultado es el resultado del único método aplicable: el método object-widthpara la clase button.

? ( ​​ancho-objeto ( crear-instancia 'botón )) 80

También podemos calcular el ancho de un bordered-button. Llamando a object-widthse calcula 84. El resultado es la suma de los resultados de los dos métodos aplicables: el método object-widthpara la clase buttony el método object-widthpara la clase border-mixin.

? ( ​​ancho-objeto ( crear-instancia 'bordered-button )) 84

C++

Mezclar con CRTP

En C++ , la forma tradicional de implementar mixins es utilizando el patrón de plantilla curiosamente recurrente (CRTP).

importar std ;using std :: string ; using std :: three_way_comparable ; using std :: tuple ;plantilla < typename Host > concepto HasKey = requiere ( const Host & x ) { { x . key () } -> three_way_comparable < bool > ; };template < HasKey Host > class CompareByKey { protected : CompareByKey () = default ; ~ CompareByKey () = default ; public : // usa un tipo deducido para permitir strong_ordering cuando sea posible, // pero mantén otros ordenamientos si es necesario [[ nodiscard ]] friend auto operator <=> ( const Host & lhs , const Host & rhs ) noexcept { return lhs . key () <=> rhs . key (); }[[ nodiscard ]] friend bool operator == ( const Host & lhs , const Host & rhs ) noexcept { return lhs . key () == rhs . key (); } };clase Persona : público CompareByKey < Persona > { privado : cadena nombre ; entero edad ; público : Persona ( cadena nombre , entero edad ) : nombre { std :: mover ( nombre )}, edad { edad } {}[[ nodiscard ]] tupla < const string & , const int &> clave () const noexcept { return std :: tie ( nombre , edad ); } };

Mixin con anotaciones

Desde C++26 , C++ puede usar anotaciones para la reflexión para implementar mixins.

importar std ;using std :: hash ; using std :: string ; using std :: vector ; using std :: meta :: info ;plantilla < typename Host > struct EqualityMixin { [[ nodiscard ]] bool operator == ( const Host & other ) const noexcept { const Host & self = static_cast < const Host &> ( * this );plantilla para ( constexpr info m : std :: meta :: nonstatic_data_members_of ( ^^ Host )) { si ( ! ( self .[ : m : ] == other .[ : m : ])) { devolver falso ; } } devolver verdadero ; }[[ nodiscard ]] bool operator != ( const Host & other ) const noexcept { return ! ( * this == other ); } };plantilla < typename Host > struct HashMixin { static constexpr uint64_t FNV_PRIME = 0x9e3779b9 ;[[ nodiscard ]] size_t hash () const noexcept { const Host & self = static_cast < const Host &> ( * this ); size_t h = 0 ; template for ( constexpr info m : std :: meta :: nonstatic_data_mebers_of ( ^^ Host )) { h ^= hash < [ : std : meta :: type_of ( m ) : ] > {}( self .[ : m : ]) + FNV_PRIME + ( h << 6 ) + ( h >> 2 ); } return h ; } };plantilla < typename Host > struct ZeroMixin { void zero () { Host & self = static_cast < Host &> ( * this ); plantilla para ( constexpr info m : std :: meta :: nonstatic_data_mebers_of ( ^^ Host )) { self .[ : m : ] = {}; } } };// almacena las plantillas mixin como parámetros de la etiqueta de anotación // los parámetros se pueden recuperar usando // std::meta::template_arguments_of() template < template < typename > typename ... Ms > struct Mixin {};struct [[ = Mixin < EqualityMixin , HashMixin , ZeroMixin > {}]] Vec2 { double x = 0.0 ; // coordenada x double y = 0.0 ; // coordenada y };struct [[ = Mixin < EqualityMixin , HashMixin , ZeroMixin > {}]] Pixel { uint8_t r = 0 ; // valor rojo del píxel uint8_t g = 0 ; // valor verde del píxel uint8_t b = 0 ; // valor azul del píxel uint8_t a = 255 ; // valor alfa del píxel };clase [[ = Mixin < HashMixin , ZeroMixin > {}]] Persona { privado : cadena nombre ; entero edad ; público : Persona ( cadena nombre , entero edad ) : nombre { std :: mover ( nombre )}, edad { edad } {}// ... };

D

En el lenguaje de programación D , existen dos tipos de mixins: mixins de cadena y mixins de plantilla.

import std.stdio ;mixin template AddFunction () { void addedFunction () { writeln ( "Función añadida desde el mixin!" ); } }clase MyClass { mixin AddFunction ; // Inyecta addedFunction() en MyClass }void main () { // Mixin de cadenas string code = `  writeln("¡Hola desde un mixin de cadenas!");  ` ;mixin ( código ); // Esto inyecta y ejecuta el código writeln// Mixin de plantilla MyClass obj = new MyClass (); obj . addedFunction (); }

Java

Los mixins se pueden emular en Java utilizando implementaciones de métodos predeterminados en las interfaces.

import java.time.Instant ;interface LoggerMixin { default void log ( String fmt , Object ... args ) { System . out . printf ( "[LOG]: %s" , String . format ( fmt , args )); } }interface TimestampMixin { default String currentTimestamp () { Instant . now (). toString (); } }class MyService implements LoggerMixin , TimestampMixin { public void doWork () { log ( "Comenzando el trabajo en %s" , currentTimestamp ()); } }public class Main { public static void main ( String [] args ) { MyService service = new MyService (); service . doWork (); } }

JavaScript

El objeto literal y extendel enfoque

Técnicamente es posible agregar comportamiento a un objeto mediante la vinculación de funciones a claves del mismo. Sin embargo, esta falta de separación entre estado y comportamiento tiene inconvenientes:

  1. Combina propiedades del dominio del modelo con las del dominio de la implementación.
  2. No comparten comportamientos comunes. Los metaobjetos resuelven este problema separando las propiedades específicas del dominio de los objetos de sus propiedades específicas de comportamiento. [ 18 ]

Se utiliza una función de extensión para mezclar el comportamiento en lo siguiente (con anotaciones de tipo de TypeScript ): [ 19 ]

interface NameMixin { fullName () : string ; rename ( first : string , last : string ) : this ; }clase Halfling { firstName : string ; lastName : string ;constructor ( first : string , last : string ) { this . firstName = first ; this . lastName = last ; } }const mixin : NameMixin = { fullName ( ) { return this.firstName + ' ' + this.lastName ; } , rename ( first : string , last : string ) { this.firstName = first ; this.lastName = last ; return this ; } } ;// Una función de extensión function extend < T , U > ( obj : T , mixin : U ) : T & U { Object . keys ( mixin ). forEach ( key => { ( obj as any )[ key ] = ( mixin as any )[ key ]; }); return obj as T & U ; }// Mezclar los otros métodos extend ( Halfling . prototype , mixin );// Indica que Halfling ahora incluye los métodos mixin: interface Halfling extends NameMixin {}const sam : Halfling = new Halfling ( 'Sam' , 'Loawry' ); const frodo : Halfling = new Halfling ( 'Freeda' , 'Baggs' );console.log ( sam.fullName ( ) ); // Sam Loawry console.log ( frodo.fullName ( ) ) ; // Freeda Baggssam.cambiar_nombre ( ' Samwise' , ' Gamgee' ); frodo.cambiar_nombre ( 'Frodo' , ' Baggins ' );console.log ( sam.fullName ( ) ); // Samwise Gamgee console.log ( frodo.fullName ( ) ) ; // Frodo Baggins

Mezclar con usarObject.assign()

interfaz Persona { nombre : cadena ; ciudad : cadena ; nacimiento : cadena ; }interfaz Mix1 { toString () : string ; age () : number ; }interfaz Mix2 { toString () : string ; }tipo PersonaConMezclas = Persona & Mezcla1 & Mezcla2 ;// Creando un objeto const obj1 : Person = { name : 'Marcus Aurelius' , city : 'Rome' , born : '121-04-26' };// Mixin 1 const mix1 : Mix1 = { toString () { return ` ${ this . name } nació en ${ this . city } en ${ this . born } ` ; }, age () { const year : number = new Date (). getFullYear (); const born : number = new Date ( this . born ). getFullYear (); return year - born ; } };// Mixin 2 const mix2 : Mix2 = { toString () { return ` ${ this . name } - ${ this . city } - ${ this . born } ` ; } };// Agregando los métodos de los mixins al objeto usando Object.assign() const mixedObj : PersonWithMixins = Object . assign ( obj1 , mix1 , mix2 ) as PersonWithMixins ;console.log ( obj1.toString ( )); // Marco Aurelio - Roma - 121-04-26 console.log ( ` Su edad es ${ obj1.age ( ) } a día de hoy` ) ; // Su edad es 1897 a día de hoy

El enfoque Flight-Mixin basado en funciones puras y delegación

Aunque el primer enfoque descrito es el más extendido, el siguiente se acerca más a lo que ofrece fundamentalmente el núcleo del lenguaje JavaScript: la delegación .

Dos patrones basados ​​en objetos de función ya hacen el trabajo sin necesidad de una implementación de terceros extend.

interfaz FirstLast < T > { first () : T | indefinido ; last () : T | indefinido ; }// Extiende el tipo Array globalmente interface Array < T > extends FirstLast < T > {}// Implementación const EnumerableFirstLast = ( function () { const first = function < T > ( this : T []) : T | undefined { if ( this . length === 0 ) { return null ; } return this [ 0 ]; };const last = function < T > ( this : T []) : T | undefined { return this [ this . length - 1 ]; };return function ( this : any ) { this . first = first ; this . last = last ; }; }());// Aplicación - delegación explícita: // aplicando el comportamiento enumerable [first] y [last] al [prototipo] de [Array]. EnumerableFirstLast . call ( Array . prototype );// Ahora puedes hacer: const a : number [] & FirstLast < number > = [ 1 , 2 , 3 ]; a . first (); // 1 a . last (); // 3

Pitón

En Python , un ejemplo del concepto de mixin se encuentra en el socketservermódulo [ 20 ] , que tiene una socketserver.UDPServerclase y una socketserver.TCPServerclase. Estas actúan como servidores para servidores de sockets UDP y TCP , respectivamente. Además, existen dos clases mixin: socketserver.ForkingMixIny socketserver.ThreadingMixIn. Normalmente, todas las conexiones nuevas se manejan dentro del mismo proceso. Al extender socketserver.TCPServercon de la socketserver.ThreadingMixInsiguiente manera:

from socketserver import TCPServer , ThreadingMixInclase ThreadingTCPServer ( ThreadingMixIn , TCPServer ): pasar

La socketserver.ThreadingMixInclase agrega funcionalidad al servidor TCP de tal manera que cada nueva conexión crea un nuevo hilo . Usando el mismo método, socketserver.ThreadingUDPServerse puede crear un sin tener que duplicar el código en socketserver.ThreadingMixIn. Alternativamente, usar socketserver.ForkingMixInprovocaría que el proceso se bifurcara para cada nueva conexión. Claramente, la funcionalidad para crear un nuevo hilo o bifurcar un proceso no es muy útil como una clase independiente.

En este ejemplo de uso, los mixins proporcionan una funcionalidad subyacente alternativa sin afectar la funcionalidad como servidor de sockets.

Rubí

La mayor parte del mundo Ruby se basa en mixins a través de Modules. El concepto de mixins se implementa en Ruby mediante la palabra clave includea la que pasamos el nombre del módulo como parámetro .

Ejemplo:

clase Student incluye Comparable # La clase Student hereda del módulo Comparable usando la palabra clave 'include' attr_accessor :name , :scoredef inicializar ( nombre , puntuación ) @nombre = nombre @puntuación = puntuación fin# Incluir el módulo Comparable requiere que la clase implementadora defina el operador de comparación <=> # Aquí está el operador de comparación. Comparamos 2 instancias de estudiantes en función de sus puntuaciones.def <=> ( otro ) @puntuación <=> otro . puntuación fin# Y aquí viene lo bueno: tengo acceso gratuito a <, <=, >, >= y otros métodos de la Interfaz Comparable .s1 = Estudiante.new ( " Peter " , 100 ) s2 = Estudiante.new ( " Jason " , 90 )s1 > s2 #verdadero s1 <= s2 #falso

En otros idiomas

En el lenguaje de contenido web Curl , se utiliza la herencia múltiple, ya que las clases sin instancias pueden implementar métodos. Los mixins comunes incluyen todos ControlUIlos skinnables que heredan de SkinnableControlUI, los objetos delegados de la interfaz de usuario que requieren menús desplegables que heredan de StandardBaseDropdownUI y clases mixin con nombres explícitos como FontGraphicMixiny FontVisualMixinla NumericAxisMixin-ofclase. La versión 7.0 añadió acceso a la biblioteca para que los mixins no necesiten estar en el mismo paquete ni ser públicos abstractos. Los constructores de Curl son fábricas que facilitan el uso de la herencia múltiple sin la declaración explícita de interfaces o mixins.

Interfaces y características

Java 8 introduce una nueva característica: los métodos predeterminados para interfaces. [ 21 ] Básicamente, permite definir un método en una interfaz con aplicación en el escenario en el que se debe agregar un nuevo método a una interfaz después de que se haya completado la configuración de programación de la clase de la interfaz. Agregar una nueva función a la interfaz implica implementar el método en cada clase que la utilice. Los métodos predeterminados son útiles en este caso, ya que se pueden introducir en una interfaz en cualquier momento y tienen una estructura implementada que luego utilizan las clases asociadas. Por lo tanto, los métodos predeterminados añaden la capacidad de aplicar el concepto de mixin en Java.

Las interfaces combinadas con la programación orientada a aspectos también pueden producir mixins completos en lenguajes que admiten tales características, como C# o Java. Además, mediante el uso del patrón de interfaz de marcador , la programación genérica y los métodos de extensión, C# 3.0 tiene la capacidad de imitar mixins. Con Dart 2.7 y C# 3.0 llegó la introducción de los métodos de extensión que se pueden aplicar, no solo a clases, sino también a interfaces. Los métodos de extensión proporcionan funcionalidad adicional a una clase existente sin modificar la clase. Entonces es posible crear una clase auxiliar estática para funcionalidad específica que define los métodos de extensión. Debido a que las clases implementan la interfaz (incluso si la interfaz real no contiene ningún método o propiedad para implementar), también tomará todos los métodos de extensión. [ 3 ] [ 4 ] [ 22 ] C# 8.0 agrega la característica de métodos de interfaz predeterminados. [ 23 ] [ 24 ]

ECMAScript (en la mayoría de los casos implementado como JavaScript) no necesita imitar la composición de objetos copiando campos paso a paso de un objeto a otro. Admite de forma nativa [ 25 ] la composición de objetos basada en Trait y mixin [ 26 ] [ 27 ] a través de objetos de función que implementan un comportamiento adicional y luego se delegan a través de callo applya objetos que necesitan dicha nueva funcionalidad.

Scala

Scala posee un sistema de tipos rico , y los Traits forman parte de él, lo que ayuda a implementar el comportamiento de los mixins. Como su nombre indica, los Traits se utilizan generalmente para representar una característica o aspecto distintivo que normalmente es ortogonal a la responsabilidad de un tipo concreto o, al menos, de una instancia determinada. [ 28 ] Por ejemplo, la capacidad de cantar se modela como una característica ortogonal: podría aplicarse a pájaros, personas, etc.

trait Cantante { def cantar { println ( " cantando … " ) } //más métodos }La clase Bird extiende Singer

Aquí, Bird ha mezclado todos los métodos del rasgo en su propia definición como si la clase Bird hubiera definido el método sing() por sí misma.

Como extendstambién se usa para heredar de una superclase, en el caso de un rasgo extendsse usa si no se hereda ninguna superclase y solo para mezclar en el primer rasgo. Todos los rasgos siguientes se mezclan usando la palabra clave with.

La clase Persona extiende la clase Actor con la clase Cantante . La clase Actor extiende la clase Cantante con la clase Intérprete.

Scala permite incorporar un rasgo (creando un tipo anónimo ) al crear una nueva instancia de una clase. En el caso de una instancia de la clase Person, no todas las instancias pueden cantar, pero podemos crear una instancia específica de Person que sí pueda hacerlo.

clase Persona { def decir { println ( " Humano " ) } //más métodos }val singingPerson = new Person with Singer singingPerson.sing

Óxido

Rust hace un uso extensivo de mixins a través de traits . Los traits, al igual que en Scala, permiten a los usuarios implementar comportamientos para un tipo definido. También se utilizan para genéricos y despacho dinámico , lo que permite que los tipos que implementan un trait se utilicen indistintamente de forma estática o dinámica en tiempo de ejecución. [ 29 ]

// Permite que los tipos "hablen" trait Speak { fn speak ( & self );// Rust permite a los implementadores definir implementaciones predeterminadas para las funciones definidas en los traits fn greet ( & self ) { println! ( "Hola!" ) } }struct Perro { nombre : String , }impl Hablar para Perro { fn speak ( & self ) { println! ( "{} dice, '¡Guau guau!'" , self . name ); } }struct Robot { nombre : String , }impl Hablar para Robot { fn speak ( & self ) { println! ( "{} dice 'Beep beep boop boop', self.name" ); }// Aquí sobrescribimos la definición de Speak::greet para Robot fn greet ( & self ) { println! ( "Robot {} dice '¡Hola!'" , self . name ) } }

Rápido

En Swift, la función Mixin se puede implementar utilizando una característica del lenguaje llamada Implementación predeterminada en la extensión de protocolo.

protocolo ErrorDisplayable { func error ( mensaje : String ) }extensión ErrorDisplayable { func error ( mensaje : String ) { // Hacer lo necesario para mostrar un error //... print ( mensaje ) } }struct NetworkManager : ErrorDisplayable { func onError () { error ( "Por favor, compruebe su conexión a Internet." ) } }

Véase también

Referencias

  1. 1 2 "Uso de mixins con Python | Linux Journal" . www.linuxjournal.com . Consultado el 23 de mayo de 2023 .
  2. 1 2 AOL.COM, Bapopik en (3 de agosto de 2002). "Mix-Ins (Steve's ice cream, Boston, 1975)" . Recuperado el 23 de mayo de 2023 .
  3. 1 2 "Implementación de Mixins con métodos de extensión de C#" . Zorched / Solución de una línea . Consultado el 23 de mayo de 2023 .
  4. 1 2 "Sé la respuesta (es 42) : Mixins y C#" . 4 de septiembre de 2006. Archivado del original el 4 de septiembre de 2006. Consultado el 23 de mayo de 2023 . 
  5. Boyland, John; Giuseppe Castagna (26 de junio de 1996). «Compilación con seguridad de tipos de especialización covariante: un caso práctico» . En Pierre Cointe (ed.). ECOOP '96, Programación orientada a objetos: 10.ª Conferencia Europea . Springer. pp. 16–17 . ISBN  9783540614395Consultado el 17 de enero de 2014 .
  6. "Mix In" . wiki.c2.com . Consultado el 23 de mayo de 2023 .
  7. "Trabajando con Mixins en Ruby" . 8 de julio de 2015.
  8. "Reutilización en POO: Herencia, Composición y Mixins" .
  9. "Más allá de los mixins » Justin Leitgeb" . Archivado del original el 25/09/2015 . Consultado el 16/09/2015 . 
  10. "Herencia basada en mixins" (PDF) .
  11. Bill Wagner. "Crear tipos mixin usando métodos de interfaz predeterminados" . docs.microsoft.com . Consultado el 18 de abril de 2022 .
  12. "ET: Herencia" . www.eiffel.org . 3 de junio de 2024. Consultado el 5 de noviembre de 2024 .
  13. slava (25/01/2010). "Factor/Características/El lenguaje" . concatenative.org . Consultado el 15/05/2012 . Principales características del lenguaje Factor: … Sistema de objetos con herencia, funciones genéricas, despacho de predicados y mixins.
  14. "Clases - MATLAB y Simulink - MathWorks India" .
  15. Alain Frisch (14 de junio de 2013). "Objetos Mixin" . LexiFi . Consultado el 29 de marzo de 2022 .
  16. «Composición de clases Mixin» . Escuela Politécnica Federal de Lausana . Consultado el 16 de mayo de 2014 .
  17. "XOTcl - Tutorial" . media.wu-wien.ac.at . Consultado el 23 de mayo de 2023 .
  18. "Mixins, reenvío y delegación en JavaScript" .
  19. "DRY JavaScript con mixins" . Archivado del original el 21/09/2015 . Consultado el 16/09/2015 .
  20. "cpython: 2cb530243943 Lib/socketserver.py" . hg.python.org . Consultado el 23-05-2023 .
  21. "Métodos predeterminados (Tutoriales de Java™ > Aprendiendo el lenguaje Java > Interfaces y herencia)" .
  22. Mixins, genéricos y métodos de extensión en C#
  23. "Métodos de extensión" . flutterbyexample.com . Archivado del original el 23 de septiembre de 2020. Consultado el 23 de mayo de 2023 .
  24. "Crear tipos mixin usando métodos de interfaz predeterminados | Microsoft Docs" . 13 de abril de 2020. Archivado del original el 13 de abril de 2020. Consultado el 23 de mayo de 2023 .
  25. Seliger, Peter (11 de abril de 2014). "Drehtür: Los muchos talentos de JavaScript" . Drehtür . Consultado el 23 de mayo de 2023 .
  26. Croll, Angus (31 de mayo de 2011). "Una nueva mirada a los Mixins de JavaScript" . JavaScript, JavaScript... Recuperado el 23 de mayo de 2023 .
  27. "javascript-code-reuse-patterns/source/components/composition en master · petsel/javascript-code-reuse-patterns" . GitHub . Consultado el 23 de mayo de 2023 .
  28. "Scala en la práctica: Traits como Mixins – Motivación" . 19 de julio de 2009.
  29. "Traits: Defining Shared Behavior - the Rust Programming Language" .
  • MixIn en el repositorio de patrones de Portland
  • Mixins en ActionScript
  • El libro "The Common Lisp Object System: An Overview" de Richard P. Gabriel y Linda DeMichiel ofrece una buena introducción a la motivación para definir clases mediante funciones genéricas.