Articulo de referencia

Constructor (programación orientada a objetos)

En la programación orientada a objetos basada en clases , un constructor (abreviatura: ctor ) es un tipo especial de función que se llama para crear un objeto . Prepara el nuevo...

En la programación orientada a objetos basada en clases , un constructor (abreviatura: ctor ) es un tipo especial de función que se llama para crear un objeto . Prepara el nuevo objeto para su uso, a menudo aceptando argumentos que el constructor utiliza para establecer las variables miembro necesarias .

Un constructor se asemeja a un método de instancia , pero se diferencia de este en que no tiene un tipo de retorno explícito , no se hereda implícitamente y suele tener reglas diferentes para los modificadores de ámbito. Los constructores a menudo tienen el mismo nombre que la clase que los declara . Su función es inicializar los miembros de datos del objeto y establecer el invariante de la clase , fallando si el invariante no es válido. Un constructor bien escrito deja el objeto resultante en un estado válido . Los objetos inmutables deben inicializarse en un constructor.

La mayoría de los lenguajes permiten sobrecargar el constructor, de modo que puede haber más de un constructor para una clase, con diferentes parámetros. Algunos lenguajes consideran ciertos tipos especiales de constructores. Los constructores, que concretamente utilizan una sola clase para crear objetos y devolver una nueva instancia de la clase, se abstraen mediante fábricas , que también crean objetos, pero pueden hacerlo de diversas maneras, utilizando múltiples clases o diferentes esquemas de asignación, como un grupo de objetos .

Tipos

Constructores parametrizados

Los constructores que aceptan al menos un argumento se denominan constructores parametrizados. Al declarar un objeto en un constructor parametrizado, los valores iniciales deben pasarse como argumentos a la función constructora. La forma habitual de declaración de objetos puede no funcionar. Los constructores pueden llamarse de forma explícita o implícita. El método de llamada implícita al constructor también se conoce como método abreviado.

clase Point { private : int x ; int y ; public : Point () = default ; Point ( int x , int y ) : x { x }, y { y } {} // Constructor parametrizado };
Punto p = Punto ( 0 , 50 ); // Llamada explícita. Punto p2 ( 0 , 50 ); // Llamada implícita.

Constructores predeterminados

Si el programador no proporciona un constructor para una clase instanciable, el compilador de Java inserta un constructor predeterminado en el código. Este constructor se conoce como constructor predeterminado. No se encontraría en el código fuente (el archivo .java ) ya que se insertaría en el código durante la compilación y existe en el archivo .class . El comportamiento del constructor predeterminado depende del lenguaje. Puede inicializar los miembros de datos a cero u otros valores iguales, o puede no hacer nada en absoluto. En Java, un "constructor predeterminado" se refiere a un constructor nulo que es generado automáticamente por el compilador si no se han definido constructores para la clase o en ausencia de constructores definidos por el programador (por ejemplo, en Java, el constructor predeterminado llama implícitamente al constructor nulo de la superclase y luego ejecuta un cuerpo vacío). Todos los campos se dejan en su valor inicial de (tipos enteros), (tipos de punto flotante), (tipo booleano) o (tipos de referencia), etc.00.0falsenull

clase Punto { privado : int x ; int y ; público : Punto ( int x = 0 , int y = 0 ); // Constructor predeterminado. };

Constructores de copia

Al igual que C++, Java también admite constructores de copia. Sin embargo, a diferencia de C++, Java no crea un constructor de copia predeterminado, incluso si no se especifica ninguno. Los constructores de copia definen las acciones que realiza el compilador al copiar objetos de una clase. Un constructor de copia tiene un parámetro formal que es el tipo de la clase (el parámetro puede ser una referencia a un objeto). Se utiliza para crear una copia de un objeto existente de la misma clase. Aunque ambas clases sean idénticas, se considera un constructor de conversión. Si bien los constructores de copia suelen abreviarse como `copy ctor` o `cctor`, no tienen relación con los constructores de clase utilizados en .NET, que emplean la misma abreviatura.

Constructores de conversión

Los constructores de conversión permiten al compilador crear implícitamente un objeto de una clase a partir de un objeto de un tipo diferente. Estos constructores suelen invocarse implícitamente para convertir argumentos u operandos al tipo adecuado, pero también pueden llamarse explícitamente.

Mover constructores

En C++, los constructores de movimiento toman una referencia Rvalue a un objeto de la clase y se utilizan para implementar la transferencia de propiedad de los recursos del objeto parámetro.

Sintaxis

  • Java , C++ , C# , ActionScript , PHP 4 y MATLAB tienen una convención de nomenclatura en la que los constructores tienen el mismo nombre que la clase con la que están asociados.
  • En C y Rust (lenguajes de programación) , no existen constructores a nivel de lenguaje. En C, los objetos se crean mediante un inicializador de estructura o una función que crea una instancia de dicho objeto. De manera similar, en Rust, los objetos se crean como literales de estructura, pero también pueden incluir una función asociada similar a un constructor (generalmente llamada `build` new, `build` from, etc.).
  • En Crystal , de forma similar a Python, el constructor se divide entre dos métodos: newy initialize. El compilador define el newmétodo, requiriendo únicamente que el usuario defina initialize. [ 1 ] Aunque el compilador de Crystal lo define automáticamente, el usuario puede definir manualmente new, e incluso prescindir del uso de default newy definir sus propios constructores.
  • En PHP 5, se recomienda un nombre para un constructor __construct. Para garantizar la compatibilidad con versiones anteriores, se llamará a un método con el mismo nombre que la clase si __constructno se encuentra el método. Desde PHP 5.3.3, esto solo funciona para clases sin espacio de nombres. [ 2 ]
  • En PHP 7, siempre debes nombrar el constructor como __construct. Los métodos con el mismo nombre que la clase provocarán un error de nivel E_DEPRECATED. [ 2 ]
  • En Perl , por convención, los constructores se llaman "new" y tienen que realizar una cantidad considerable de creación de objetos.
  • En el sistema de objetos Moose para Perl, los constructores (llamados new) se crean automáticamente y se extienden especificando un BUILDmétodo.
  • En Visual Basic .NET , el constructor se llama " New".
  • En Python , el constructor se divide en dos métodos, " __new__" y " __init__". El __new__método es responsable de asignar memoria para la instancia y recibe la clase como argumento (convencionalmente llamado " cls"). Al __init__método (a menudo llamado "inicializador") se le pasa la instancia recién creada como argumento (convencionalmente llamado " self"). [ 3 ]
  • Los constructores de Object Pascal se indican mediante la palabra clave " constructor" y pueden tener nombres definidos por el usuario (pero en su mayoría se llaman " Create").
  • En Objective-C , el método constructor se divide en dos métodos, " alloc" y " init", donde el allocmétodo reserva (asigna) memoria para una instancia de la clase, y el initmétodo maneja la mayor parte de la inicialización de la instancia. Una llamada al método " new" invoca tanto el método alloccomo el initmétodo, para la instancia de la clase.

Organización de la memoria

En Java, C# y VB .NET, el constructor crea objetos de tipo referencia en el montón, mientras que los tipos primitivos (como int, double, etc.) se almacenan en la pila (aunque algunos lenguajes permiten asignar manualmente objetos en la pila mediante un stackallocmodificador). VB .NET y C# también permiten el uso del newoperador para crear objetos de tipo valor, pero estos objetos se crean en la pila independientemente de si se usa el operador o no. En estos lenguajes, la destrucción de un objeto ocurre cuando este no tiene referencias y luego es destruido por el recolector de basura.

En C++, los objetos se crean en la pila cuando se invoca el constructor sin el newoperador `for`, y en el montón cuando se invoca con el newoperador `for` (que devuelve un puntero al objeto). Los objetos de la pila se eliminan implícitamente cuando salen del ámbito, mientras que los objetos del montón deben eliminarse implícitamente mediante un destructor o explícitamente mediante el deleteoperador `for`. Al utilizar el patrón " Adquisición de recursos es inicialización " (RAII), la gestión de recursos se puede simplificar enormemente.

Detalles del idioma

Los constructores se implementan en diferentes lenguajes de programación de diversas maneras, entre las que se incluyen:

do

En C , no existen constructores. Sin embargo, se pueden definir funciones para crear un objeto, de forma similar a un constructor.

#include <stdlib.h>typedef struct { char * nombre ; int edad ; } Persona ;// Este método crea una instancia de Person Person * createPerson ( const char name [], int age ) { Person * p = ( Person * ) malloc ( sizeof ( Person )); if ( ! p ) { return NULL ; } strcpy ( p -> name , name ); p -> age = age ; return p ; }// Este método destruye una instancia de Person void destroyPerson ( Person * p ) { if ( p ) { free ( p -> name ); free ( p ); } }

C++

En C++ , el nombre del constructor es el mismo que el de la clase. No devuelve ningún valor. Puede tener parámetros, al igual que cualquier función miembro . Las funciones constructoras suelen declararse en la sección pública, pero también pueden declararse en las secciones protegida y privada si el usuario desea restringir el acceso a ellas.

El constructor tiene dos partes. La primera es la lista de inicialización, que sigue a la lista de parámetros y precede al cuerpo del método. Comienza con dos puntos y las entradas están separadas por comas. La lista de inicialización no es obligatoria, pero ofrece la oportunidad de proporcionar valores para los miembros de datos y evitar sentencias de asignación separadas. La lista de inicialización es obligatoria si hay constmiembros de datos de tipo referencia o miembros que no tienen lógica de constructor sin parámetros. Las asignaciones se realizan según el orden en que se declaran los miembros de datos (incluso si el orden en la lista de inicialización es diferente). [ 4 ] La segunda parte es el cuerpo, que es un cuerpo de método normal encerrado entre llaves. Generalmente es más económico y una mejor práctica usar la lista de inicialización tanto como sea posible, y usar el cuerpo del constructor solo para operaciones que no sean de asignación y asignaciones donde la lista de inicialización no se puede usar o es insuficiente por alguna otra razón.

C++ permite más de un constructor. Los demás constructores deben tener parámetros diferentes. Además, los constructores que contienen parámetros con valores predeterminados deben cumplir con la restricción de que no todos los parámetros tengan un valor predeterminado. Esta situación solo importa si existe un constructor predeterminado. El constructor de una clase base (o clases base) también puede ser llamado por una clase derivada. Las funciones constructoras no se heredan y no se puede acceder a sus direcciones. Cuando se requiere asignación de memoria, los operadores new`and` deletese llaman implícitamente.

Un constructor de copia tiene un parámetro del mismo tipo que se pasa por constreferencia, por ejemplo . Si no se proporciona explícitamente, el compilador usa el constructor de copia para cada variable miembro o simplemente copia los valores en el caso de tipos primitivos. La implementación predeterminada no es eficiente si la clase tiene miembros asignados dinámicamente (o identificadores para otros recursos), ya que puede provocar llamadas dobles a (o liberación doble de recursos) al destruirse.X(constX&rhs)delete

importar std ;clase PolarPoint { private : double x ; double y ; public : explicit PolarPoint ( double r = 1.0 , double theta = 0.0 ) : // Constructor, parámetros con valores predeterminados. x { r * std::cos ( theta ) }, y { r * std :: sin ( theta ) } /* <- Lista de inicialización */ { std :: println ( "Punto: x = {}, y = {}" , x , y ); // Cuerpo del constructor } };

Ejemplos de invocaciones:

Punto Polar a ; Punto Polar b ( 3 ); PolarPoint c ( 5 , std :: números :: pi / 4 );

Al devolver objetos desde funciones o pasar objetos por valor, se llamará implícitamente al constructor de copia de los objetos, a menos que se aplique la optimización del valor de retorno .

C++ genera implícitamente un constructor de copia predeterminado que llamará a los constructores de copia de todas las clases base y todas las variables miembro, a menos que el programador proporcione uno, elimine explícitamente el constructor de copia (para evitar la clonación) o se elimine o no sea accesible (privado) el constructor de copia de una de las clases base o variables miembro. En la mayoría de los casos que requieren un constructor de copia personalizado (por ejemplo, conteo de referencias , copia profunda de punteros), también se requiere personalizar el destructor y el operador de asignación de copia . Esto se conoce comúnmente como la Regla de tres .

DO#

Ejemplo de constructor en C# :

clase pública MyClass { entero privado a ; cadena privada b ;// Constructor público MyClass () : this ( 42 , "string" ) { }// Sobrecarga de un constructor public MyClass ( int a , string b ) { this . a = a ; this . b = b ; } }
// Código en algún lugar // Instanciando un objeto con el constructor anterior MyClass c = new MyClass ( 42 , "string" );

Desde C# 9.0, las llamadas a constructores se pueden simplificar aún más usando newexpresiones de tipo de destino, que no requieren nombrar el constructor cuando el tipo ya está dado. Llamará automáticamente al constructor del tipo nombrado antes de la variable, pero obviamente no se resolverá si se usa la deducción de tipos ( var). [ 5 ]

// Ejemplo anterior con expresiones nuevas de tipo objetivo MyClass c = new ( 42 , "string" );

constructor estático de C#

En C# , un constructor estático es un inicializador de datos estático. [ 6 ] : 111–112 Los constructores estáticos también se denominan constructores de clase . Dado que el método generado tiene el nombre .cctor , a menudo también se les llama "cctors". [ 7 ] [ 8 ]

Los constructores estáticos permiten la inicialización de variables estáticas complejas . [ 9 ] Los constructores estáticos se llaman implícitamente cuando se accede a la clase por primera vez. Cualquier llamada a una clase (estática o llamada al constructor) activa la ejecución del constructor estático. Los constructores estáticos son seguros para subprocesos e implementan un patrón singleton . Cuando se utilizan en una clase de programación genérica , los constructores estáticos se llaman en cada nueva instanciación genérica, uno por tipo. [ 10 ] : 38 [ 6 ] : 111 Las variables estáticas también se instancian.

clase pública MyClass { entero estático privado _A ;// Constructor normal static MyClass () { _A = 32 ; }// Constructor predeterminado estándar público MyClass () {} }
// Código en algún lugar // Instanciar un objeto con el constructor anterior // justo antes de la instanciación // Se ejecuta el constructor estático variable y _A es 32 MyClass c = new MyClass ();

Lenguaje de marcado ColdFusion (CFML)

El lenguaje de marcado ColdFusion (CFML) utiliza un método llamado ' init' como método constructor.

Queso.cfc

componente { // propiedades propiedad nombre = "cheeseName" ;// función constructora Cheese init ( cadena requerida cheeseName ) { variables . cheeseName = arguments . cheeseName ; return this ; } }

Crear una instancia de un queso.

miQueso = nuevo Queso ( 'Cheddar' );

Desde ColdFusion 10, [ 11 ] CFML también admite la especificación del nombre del método constructor:

component initmethod = "Cheese" { // propiedades property name = "cheeseName" ;// función constructora Cheese Cheese ( cadena requerida cheeseName ) { variables . cheeseName = arguments . cheeseName ; return this ; } }

Cristal

En Crystal, el usuario define un initializemétodo, que el compilador utiliza para definir un newmétodo para asignar memoria para el objeto y llamar al método definido por el usuario. El usuario también puede definir manualmente newo definir un método equivalente con un nombre diferente, si lo desea (el código para ambos initializese newmuestra aquí). Aunque este fragmento define un class, el procedimiento es idéntico para Crystal struct.

clase Car # el inicializador, que es un método de instancia. def initialize ( make : String , year : Int ) @make = make @year = year end # el asignador, que es un método de clase, denotado por el prefijo "self." # tenga en cuenta que `new` toma los mismos argumentos que `initialize` def self . new ( make : String , year : Int ) # asigna memoria para la instancia instance = Car . allocate # llama al método initialize de la instancia usando los parámetros proporcionados instance . initialize make , year # devuelve la instancia instance end end# Instanciar un nuevo `Coche` de la siguiente manera: old_car = Car . new ( "Chevrolet" , 1947 )

Eiffel

En Eiffel , las rutinas que inicializan nuevos objetos se denominan procedimientos de creación . Los procedimientos de creación tienen las siguientes características:

  • Los procedimientos de creación no tienen un tipo de retorno explícito (por definición de procedimiento ). [ a ]
  • Los procedimientos de creación se nombran.
  • Los procedimientos de creación se designan por su nombre como procedimientos de creación en el texto de la clase.
  • Los procedimientos de creación pueden invocarse explícitamente para reinicializar objetos existentes.
  • Cada clase efectiva (es decir, concreta o no abstracta) debe designar al menos un procedimiento de creación.
  • Los procedimientos de creación deben dejar el objeto recién inicializado en un estado que satisfaga el invariante de clase. [ b ]

Aunque la creación de objetos implica algunas sutilezas, [ 12 ] la creación de un atributo con una declaración típica x: Ttal como se expresa en una instrucción de creación create x.makeconsta de la siguiente secuencia de pasos:

  • Crea una nueva instancia directa del tipo T. [ c ]
  • Ejecutar el procedimiento de creación makeen la instancia recién creada.
  • Adjunte el objeto recién inicializado a la entidad x.

En el primer fragmento a continuación, POINTse define la clase. El procedimiento makese codifica después de la palabra clave feature.

La palabra clave createintroduce una lista de procedimientos que se pueden usar para inicializar instancias. En este caso, la lista incluye default_create, un procedimiento con una implementación vacía heredada de la clase ANY, y el makeprocedimiento codificado dentro de la clase.

clase POINT crear default_create , hacercaracterísticahacer ( a_x_value : REAL ; a_y_value : REAL ) hacer x := a_x_value y := a_y_value finx : REAL -- Coordenada Xy : REAL -- Coordenada Y ...

En el segundo fragmento, una clase que es cliente de POINTtiene declaraciones my_point_1y my_point_2de tipo POINT.

En el código procedimental, my_point_1se crea como el origen (0.0, 0.0). Como no se especifica ningún procedimiento de creación, se utiliza el procedimiento default_createheredado de la clase ANY. Esta línea podría haberse codificado como create my_point_1.default_create. Solo los procedimientos nombrados como procedimientos de creación pueden usarse en una instrucción con la createpalabra clave. A continuación, hay una instrucción de creación para my_point_2, que proporciona valores iniciales para las my_point_2coordenadas de . La tercera instrucción hace una llamada de instancia ordinaria al makeprocedimiento para reinicializar la instancia adjunta a my_point_2con valores diferentes.

mi_punto_1 : PUNTO mi_punto_2 : PUNTO ...crear my_point_1 crear my_point_2 . crear ( 3.0 , 4.0 ) my_point_2 . crear ( 5.0 , 8.0 ) ...

F#

En F# , un constructor puede incluir cualquier instrucción leto dodefinida en una clase. letLas instrucciones definen campos privados y dolas instrucciones ejecutan código. Se pueden definir constructores adicionales utilizando la newpalabra clave.

type MyClass (_ a : int , _ b : string ) = class // Constructor principal let a = _ a let b = _ b do printfn "a = %i, b = %s" a b// Constructores adicionales new (_ a : int ) = MyClass (_ a , "" ) then printfn "Parámetro entero proporcionado"nuevo (_ b : cadena ) = MyClass ( 0 , _ b ) luego printfn "Parámetro de cadena proporcionado"nuevo () = MyClass ( 0 , "" ) entonces printfn "No se ha proporcionado ningún parámetro" fin
// Código en alguna parte // Instanciando un objeto con el constructor principal let c1 = new MyClass ( 42 , "string" )// Instanciando un objeto con constructores adicionales let c2 = new MyClass ( 42 ) let c3 = new MyClass ( "string" ) let c4 = MyClass () // La palabra clave "new" es opcional

Java

En Java , los constructores se diferencian de otros métodos en que:

  • Los constructores nunca tienen un tipo de retorno explícito.
  • Los constructores no se pueden invocar directamente (la palabra clave “ new” los invoca).
  • Los constructores no deben tener modificadores que no sean de acceso.

Los constructores de Java realizan las siguientes tareas en el siguiente orden:

  1. Si no se ha definido ningún constructor, se llamará al constructor predeterminado de la superclase.
  2. Inicializa las variables miembro con los valores especificados.
  3. Ejecuta el cuerpo del constructor.

Java permite a los usuarios llamar a un constructor dentro de otro constructor usando this()la palabra clave. Pero this()debe ser la primera instrucción. [ 13 ]

clase X { public X () { // Constructor sin parámetros this ( 1 ); // Llamada al constructor System . out . println ( "Llamando al constructor predeterminado" ); }public X ( int a ) { // Constructor parametrizado System . out . println ( "Llamando al constructor parametrizado" ); } }public class Example { public static void main ( String [] args ) { X x = new X (); } }

Java proporciona acceso al constructor de la superclasesuper a través de la palabra clave.

clase X { // Declaración de variables de instancia. private int data ;// Definición del constructor. public X () { this ( 1 ); }// Sobrecarga de un constructor public X ( int input ) { data = input ; // Esto es una asignación } }clase Y extiende X { int privado data2 ;public Y () { super (); data2 = 1 ; }public Y ( int input1 , int input2 ) { super ( input1 ); data2 = input2 } }public class Example { public static void main ( String [] args ) { Y y = new Y ( 42 , 43 ); } }

Un constructor que no toma ningún argumento se denomina constructor "sin argumentos" o "sin argumentos". [ 14 ]

JavaScript/TypeScript

A partir de ES6, JavaScript tiene constructores directos como muchos otros lenguajes de programación. Se escriben de la siguiente manera:

clase FooBar { constructor ( baz ) { this . baz = baz ; } }

Esto se puede instanciar de la siguiente manera:

const foo = new FooBar ( '7' );

El equivalente a esto antes de ES6 era crear una función que instanciara un objeto como tal.

función FooBar ( baz ) { this . baz = baz ; }

Esto se instancia de la misma manera que se describió anteriormente.

El equivalente en TypeScript sería:

clase FooBar { baz : cadena ;constructor ( baz : string ) { this . baz = baz ; } }const foo : FooBar = new FooBar ( '7' );

Objeto Pascal

En Object Pascal , el constructor es similar a un método de fábrica . La única diferencia sintáctica con los métodos regulares es la palabra clave constructordelante del nombre (en lugar de procedureo function). Puede tener cualquier nombre, aunque la convención es tener Createcomo prefijo, como en CreateWithFormatting. Crear una instancia de una clase funciona como llamar a un método estático de una clase: TPerson.Create('Peter').

programa OopProgram ;tipo TPerson = clase privada FName : string ; propiedad pública Name : string leer FName ; constructor Create ( AName : string ) ; fin ;constructor TPerson . Create ( AName : string ) ; begin FName := AName ; end ;var Person : TPerson ; begin Person := TPerson . Create ( 'Peter' ) ; // asigna una instancia de TPerson y luego llama a TPerson.Create con el parámetro AName = 'Peter' end .

OCaml

En OCaml , existe un único constructor. Los parámetros se definen justo después del nombre de la clase. Se pueden usar para inicializar variables de instancia y son accesibles en toda la clase. Un método oculto anónimo initializerpermite evaluar una expresión inmediatamente después de que se haya construido el objeto. [ 15 ]

clase persona nombre apellido = objeto val nombre_completo = nombre ^ " " ^ apellidoinicializador print_endline ( "Hola, soy " ^ full_name ^ "." )método obtener_apellido = apellido fin ;;sea ​​alonzo = nueva persona "Alonzo" "Church" en (*Hola, soy Alonzo Church.*)print_endline alonzo # obtener_apellido (*Iglesia*)

PHP

En PHP versión 5 y posteriores, el constructor es un método llamado __construct()(nótese que es un doble guion bajo), que la palabra clave newllama automáticamente después de crear el objeto. Generalmente se usa para realizar inicializaciones automáticas, como la inicialización de propiedades. Los constructores también pueden aceptar argumentos; en ese caso, al newescribir la instrucción, también es necesario pasar los argumentos del constructor para los parámetros. [ 2 ]

clase Persona { cadena privada $nombre ;función pública __construct ( cadena $name ) : void { $this -> name = $name ; }función pública obtenerNombre () : cadena { return $this -> nombre ; } }

En PHP, una clase solo puede declarar un máximo de un método constructor. Los métodos estáticos, las clases de fábrica o los argumentos opcionales del constructor son algunas maneras de facilitar la creación de objetos de una clase PHP de múltiples formas.

Perl 5

En Perl versión 5, por defecto, los constructores son métodos de fábrica , es decir, métodos que crean y devuelven el objeto, lo que significa concretamente crear y devolver una referencia validada. Un objeto típico es una referencia a un hash, aunque rara vez se utilizan referencias a otros tipos. Por convención, el único constructor se llama ` new` , aunque se permite nombrarlo de otra manera o tener varios constructores. Por ejemplo, una clase `Person` puede tener un constructor llamado `new` , un constructor `new_from_file` que lee un archivo para obtener los atributos de `Person`, y `new_from_person` que utiliza otro objeto `Person` como plantilla.

paquete Persona ; # En Perl, los constructores se llaman 'new' por convención. sub new { # El nombre de la clase se pasa implícitamente como argumento 0. my $class = shift ;# Valores de atributo predeterminados, si los tiene. my %defaults = ( foo => "bar" );# Inicializa los atributos como una combinación de valores predeterminados y argumentos pasados. my $self = { %defaults , @_ };# Comprobar argumentos obligatorios, invariante de clase, etc. if ( not defined $self -> { first_name } ) { die "Atributo obligatorio faltante en Person->new(): first_name" ; } if ( not defined $self -> { last_name } ) { die "Atributo obligatorio faltante en Person->new(): last_name" ; } if ( defined $self -> { age } and $self -> { age } < 18 ) { die "Valor de atributo no válido en Person->new(): age < 18" ; }# Perl hace que un objeto pertenezca a una clase mediante 'bless'. bless $self , $class ; return $self ; } 1 ;

Perl 5 con Moose

En el sistema de objetos Moose para Perl, se puede omitir la mayor parte de este código repetitivo: se crea un objeto `new` por defecto, se pueden especificar los atributos y si se pueden establecer, restablecer o son obligatorios. Además, se puede incluir cualquier funcionalidad adicional del constructor en un método `BUILD` que el constructor generado por Moose llamará después de verificar los argumentos. Se puede especificar un método `BUILDARGS` para manejar argumentos del constructor que no estén en formato de referencia a hash/clave => valor.

paquete Persona ; # habilitar la construcción de objetos al estilo Moose use Moose ;# El nombre (una cadena) solo se puede establecer en el momento de la construcción ('ro') tiene first_name => ( is => 'ro' , isa => 'Str' , required => 1 ); # El apellido (una cadena) solo se puede establecer en el momento de la construcción ('ro') tiene last_name => ( is => 'ro' , isa => 'Str' , required => 1 ); # La edad (entero) se puede modificar después de la construcción ('rw') y no es necesario # pasarla al constructor. También crea un método 'has_age' que devuelve # verdadero si se ha establecido la edad tiene age => ( is => 'rw' , isa => 'Int' , predicate => 'has_age' );# Comprobar requisitos personalizados sub BUILD { my $self = shift ; if ( $self -> has_age && $self -> age < 18 ) { # no hay menores de 18 die "No se admiten menores de 18 años" ; } } 1 ;

En ambos casos, la clase Persona se inicializa de esta manera:

use Person ; my $p = Person -> new ( first_name => 'Sam' , last_name => 'Ashe' , age => 42 );

Pitón

En Python , los constructores se definen mediante uno o ambos __new__métodos __init__. Se crea una nueva instancia llamando a la clase como si fuera una función, que llama a los __new__métodos __init__. Si no se define un método constructor en la clase, se llamará al siguiente que se encuentre en el orden de resolución de métodos de la clase. [ 16 ]

En el caso típico, solo __init__es necesario definir el método. (La excepción más común se da en el caso de objetos inmutables).

clase ExampleClass : def __new__ ( cls : type , value : int ) -> 'ExampleClass' : print ( "Creando nueva instancia..." ) # Llama al constructor de la superclase para crear la instancia. instancia : 'ExampleClass' = super ( ExampleClass , cls ) .__ new__ ( cls ) return instanciadef __init__ ( self , value : int ) -> None : print ( "Inicializando instancia..." ) self . payload : int = valueif __name__ == "__main__" : exampleInstance : ExampleClass = ExampleClass ( 42 ) print ( exampleInstance . payload )

Esta impresión:

Creando nueva instancia... Inicializando instancia... 42 

Las clases normalmente actúan como fábricas de nuevas instancias de sí mismas; es decir, una clase es un objeto invocable (como una función), donde la llamada es el constructor y la llamada a la clase devuelve una instancia de esa clase. Sin embargo, __new__para fines especializados, el método puede devolver algo distinto a una instancia de la clase. En ese caso, __init__no se invoca. [ 16 ]

Raku

En Raku , se puede omitir aún más código repetitivo, dado que se hereda un método `new` predeterminado , se pueden especificar atributos y si se pueden configurar, restablecer o son obligatorios. Además, cualquier funcionalidad adicional del constructor se puede incluir en un método `BUILD` que se llamará para permitir la inicialización personalizada. Se puede especificar un método `TWEAK` para procesar posteriormente cualquier atributo que ya esté inicializado (implícitamente).

clase Persona { tiene Str $.first-name es obligatorio ; # El nombre (una cadena) solo se puede establecer en el # tiempo de construcción (el . significa "público"). tiene Str $.last-name es obligatorio ; # El apellido (una cadena) solo se puede establecer en el # tiempo de construcción (un ! significaría "privado"). tiene Int $.age es rw ; # La edad (un entero) se puede modificar después de la # construcción ('rw'), y no es obligatoria # durante la instanciación del objeto.# Crea un método 'full-name' que devuelve el nombre completo de la persona. # Se puede acceder a este método fuera de la clase. method full-name { $!first-name . tc ~ " " ~ $!last-name . tc } # Crea un método 'has-age' que devuelve verdadero si se ha establecido la edad. # Este método se usa solo dentro de la clase, por lo que se declara como "privado" # anteponiendo un ! a su nombre. method ! has-age { self . age . defined } # Comprobar el método de requisitos personalizados TWEAK { if self ! has-age && $!age < 18 { # No hay menores de 18 die "Ninguna persona menor de 18" ; } } } 

La clase Persona se instancia de la siguiente manera:

mi $p0 = Persona.new ( first-name => 'Sam' , last-name => ' Ashe' , age => 42 ); mi $ p1 = Persona.new ( first -name => 'grace' , last-name => ' hopper' ); say $ p1.full -name (); # SALIDA: «Grace Hopper␤»

Alternativamente, los parámetros con nombre se pueden especificar utilizando la sintaxis de pares de dos puntos en Perl 6:

mi $p0 = Persona . nuevo ( : nombre <Sam> , : apellido <Ashe> , : edad ( 42 ) ); mi $p1 = Persona . nuevo ( : nombre <Grace> , : apellido <Hopper> ); 

Y si ha configurado variables con nombres idénticos a los parámetros con nombre, puede usar un atajo que utilizará el nombre de la variable para el parámetro con nombre:

mi $first-name = "Sam" ; mi $last-name = "Ashe" ; mi $age = 42 ; mi $p0 = Person . new ( : $first-name , : $last-name , : $age ); 

Rubí

En Ruby , los constructores se crean definiendo un método llamado initialize. Este método se ejecuta para inicializar cada nueva instancia.

irb(main):001:0> class ExampleClass irb(main):002:1> def initialize irb(main):003:2> puts "Hola" irb(main):004:2> end irb(main):005:1> end => nil irb(main):006:0> ExampleClass . new Hola => #<ExampleClass:0x007fb3f4299118>

Óxido

Rust no tiene constructores en el sentido de la programación orientada a objetos, pero a menudo las estructuras tienen un new()método que esencialmente actúa como un constructor. El tipo de retorno generalmente se indica como Self.

struct Point { x : i32 , y : i32 , }impl Point { pub fn new ( x : i32 , y : i32 ) -> Self { Point { x , y } } }fn main () { let p : Point = Point :: new ( 10 , 20 ); println! ( "El punto está en ({}, {})" , p . x , p . y ); }

Visual Basic .NET

En Visual Basic .NET , los constructores utilizan una declaración de método con el nombre " New".

Clase Foobar Privado strData Como Cadena' Constructor Public Sub New ( ByVal someParam As String ) strData = someParam End Sub End Class
' código en otro lugar ' instanciando un objeto con el constructor anterior Dim foo As New Foobar ( ".NET" )

Véase también

Notas

  1. Las rutinas Eiffelson procedimientos o funciones . Los procedimientos nunca tienen un tipo de retorno. Las funciones siempre tienen un tipo de retorno.
  2. Dado que debe cumplirse el invariante de clase heredado, no es obligatorio llamar a los constructores de los padres.
  3. El estándar Eiffel requiere que los campos se inicialicen en el primer acceso, por lo que no es necesario realizar la inicialización de campos predeterminados durante la creación del objeto.

Referencias

  1. nuevo, inicializar y asignar , de la guía de referencia de Crystal
  2. 1 2 3 Constructores y destructores , de la documentación en línea de PHP
  3. Modelo de datos , de la documentación en línea de Python
  4. https://stackoverflow.com/questions/1242830/constructor-initialization-list-evaluation-order Constructor
  5. "Nuevas expresiones con tipo de destino" . learn.microsoft.com . Microsoft Learn. 23 de junio de 2023.
  6. ^ Albahari , José. C# 10 en pocas palabras . O'Reilly. ISBN 978-1-098-12195-2.
  7. "Fabulosas aventuras en la programación" . Eric Lippert. 6 de febrero de 2013. Consultado el 5 de abril de 2014 .
  8. Ensamblador experto de .NET 2.0 IL . APulse. 2006-01-01. ISBN 9781430202233. Consultado el 5 de abril de 2014 .
  9. "Descargar la documentación de Visual Studio 2005 (versión descatalogada) desde el Centro de descargas oficial de Microsoft" . Microsoft Store - Centro de descargas .
  10. Skeet, Jon (23 de marzo de 2019). C# en profundidad . Manning. ISBN 978-1617294532.
  11. CFComponent
  12. "Documento de especificación ISO/ECMA de Eiffel" .
  13. "Detalles sobre el constructor en Java" .
  14. "Proporcionando constructores para sus clases" . Oracle Corporation. 2013. Consultado el 20 de diciembre de 2013 .
  15. "OCaml - El manual de OCaml" . ocaml.org .
  16. 1 2 "3. Modelo de datos" . Documentación de Python .
Obtenido de " https://en.wikipedia.org/w/index.php?title=Constructor_(object-oriented_programming)&oldid=1362945879#Copy_constructors "