Saltar al contenido

Entendiendo el ejemplo de código de constructor de Factory – Dart

Posterior a de esta larga compilación de datos solucionamos esta impedimento que tienen ciertos de nuestros usuarios. Te regalamos la respuesta y nuestro objetivo es serte de mucha apoyo.

Solución:

tl; dr Utilice una fábrica en situaciones en las que no necesariamente quiero devolver un nuevo instancia de la propia clase. Casos de uso:

  • el constructor es caro, por lo que desea devolver una instancia existente, si es posible, en lugar de crear una nueva;
  • solo desea crear una instancia de una clase (el patrón singleton);
  • desea devolver una instancia de subclase en lugar de la clase en sí.

Explicación

Una clase de dardos puede tener constructores generativos o constructores de fábricas. Un constructor generativo es una función que siempre devuelve una nueva instancia de la clase. Debido a esto, no utiliza el return palabra clave. Un constructor generativo común tiene la forma:

class Person 
  String name;
  String country;

  // unnamed generative constructor
  Person(this.name, this.country);

var p = Person("...") // returns a new instance of the Person class

Un constructor de fábricas tiene restricciones más flexibles que un constructor generativo. La fábrica solo necesita devolver una instancia que sea del mismo tipo que la clase o que implemente sus métodos (es decir, satisfaga su interfaz). Esta podría ser una nueva instancia de la clase, pero también podría ser una instancia existente de la clase o una instancia nueva / existente de una subclase (que necesariamente tendrá los mismos métodos que el padre). Una fábrica puede utilizar el flujo de control para determinar qué objeto devolver y debe utilizar el return palabra clave. Para que una fábrica devuelva una nueva instancia de clase, primero debe llamar a un constructor generativo.

Explicación de la fábrica de dardos

En su ejemplo, el constructor de fábrica sin nombre primero lee de una propiedad Map llamada _cache (que, porque es Static, se almacena a nivel de clase y, por lo tanto, es independiente de cualquier variable de instancia). Si ya existe una variable de instancia, se devuelve. De lo contrario, se genera una nueva instancia llamando al constructor generativo nombrado Logger._internal. Este valor se almacena en caché y luego se devuelve. Debido a que el constructor generativo toma solo un name parámetro, el mute la propiedad siempre se inicializará para false, pero se puede cambiar con el configurador predeterminado:

var log = Logger("...");
log.mute = true;
log.log(...); // will not print

El término factory alude al Factory Pattern, que se trata de permitir que un constructor devuelva una instancia de subclase (en lugar de una instancia de clase) basándose en los argumentos proporcionados. Un buen ejemplo de este caso de uso en Dart es la clase de elemento HTML abstracto, que define docenas de funciones de constructor de fábrica con nombre que devuelven diferentes subclases. Por ejemplo, Element.div() y Element.li() regreso

y

  • elementos, respectivamente.

    En esta aplicación de almacenamiento en caché, considero que “fábrica” ​​es un nombre poco apropiado ya que su propósito es evitar llamadas al constructor generativo, y creo que las fábricas del mundo real son inherentemente generativas. Quizás un término más adecuado aquí sería “almacén”: si un artículo ya está disponible, sáquelo del estante y entréguelo. Si no es así, solicite uno nuevo.

    ¿Cómo se relaciona todo esto con los constructores nombrados? Los constructores generativos y de fábrica pueden ser sin nombre o con nombre:

    ...
      // named generative
      // delegates to the default generative constructor
      Person.greek(String name) : this(name, "Greece"); 
    
      // named factory 
      factory Person.greek(String name) 
        return Greek(name);
      
    }
    
    class Greek extends Person 
      Greek(String name) : super(name, "Greece");
    
    
    
    

    1) No hay mucha diferencia entre un static método y un constructor de fábrica.

    Para un constructor de fábrica, el tipo de retorno se fija al tipo de la clase, mientras que para un static método, puede proporcionar su propio tipo de devolución.

    Se puede invocar un constructor de fábrica con new, pero eso se volvió casi irrelevante con opcional new en Dart 2.

    Hay otras características, como las redirecciones, que se utilizan con poca frecuencia y que son compatibles con los constructores (de fábrica), pero no con static métodos.

    Probablemente sea una buena práctica utilizar un constructor de fábrica para crear instancias de clases en lugar de static métodos para hacer más obvio el propósito de la creación de objetos.

    Esta es la razón por la que se usa un constructor de fábrica en el ejemplo que publicó y quizás porque el código se escribió originalmente en Dart 1, donde permitía crear una instancia de registrador con new como con cualquier otra clase.

    2) Sí, este es un constructor con nombre y el prefix _ lo convierte en un constructor con nombre privado. Solo los constructores con nombre se pueden convertir en privados porque de lo contrario no habría lugar para agregar el _ prefix.

    Se utiliza para evitar la creación de instancias desde cualquier otro lugar que no sea el constructor de la fábrica pública. De esta forma se asegura que no puede haber más de una Logger instancia en su aplicación. El constructor de fábrica solo crea una instancia la primera vez y, para las llamadas posteriores, siempre devuelve la instancia creada anteriormente.

    Complementando la respuesta de Dave, este código muestra un ejemplo claro cuando se usa la fábrica para devolver una clase relacionada con los padres.

    Eche un vistazo a este código de https://codelabs.developers.google.com/codelabs/from-java-to-dart/#3

    Puede ejecutar este código aquí. https://dartpad.dartlang.org/63e040a3fd682e191af40f6427eaf9ef

    Realice algunos cambios para aprender cómo funcionaría en determinadas situaciones, como singletons.

    import 'dart:math';
    
    abstract class Shape 
      factory Shape(String type) 
        if (type == 'circle') return Circle(2);
        if (type == 'square') return Square(2);
        // To trigger exception, don't implement a check for 'triangle'.
        throw 'Can't create $type.';
      
      num get area;
    
    
    class Circle implements Shape 
      final num radius;
      Circle(this.radius);
      num get area => pi * pow(radius, 2);
    
    
    class Square implements Shape 
      final num side;
      Square(this.side);
      num get area => pow(side, 2);
    
    
    class Triangle implements Shape 
      final num side;
      Triangle(this.side);
      num get area => pow(side, 2) / 2;
    
    
    main() 
      try 
        print(Shape('circle').area);
        print(Shape('square').area);
        print(Shape('triangle').area);
       catch (err) 
        print(err);
      
    
    

    valoraciones y comentarios

    Si conservas algún titubeo y capacidad de innovar nuestro sección te inspiramos ejecutar una anotación y con deseo lo observaremos.

    ¡Haz clic para puntuar esta entrada!
    (Votos: 0 Promedio: 0)



    Utiliza Nuestro Buscador

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *