Constructor (programación orientada a objetos)

La versión actual de la página aún no ha sido revisada por colaboradores experimentados y puede diferir significativamente de la versión revisada el 28 de junio de 2016; las comprobaciones requieren 22 ediciones .

En la programación orientada a objetos , un constructor de clases (del inglés constructor  ) es un bloque especial de instrucciones llamado cuando se crea un objeto.

Asignación de constructor

Una de las características clave de OOP es la encapsulación : los campos internos de la clase no son directamente accesibles y el usuario solo puede trabajar con el objeto como un todo, a través de publicmétodos públicos ( ). Idealmente, cada método debe diseñarse de modo que un objeto que se encuentre en un estado "válido" (es decir, cuando se cumpla la invariante de la clase ) también se encuentre en un estado válido cuando se invoque el método. Y la primera tarea del constructor es transferir los campos del objeto a tal estado.

La segunda tarea es simplificar el uso del objeto. Un objeto no es una " cosa en sí mismo ", a menudo tiene que requerir alguna información de otros objetos: por ejemplo, un objeto File, cuando se crea, debe recibir un nombre de archivo. Esto también se puede hacer a través del método:

archivo archivo ; archivo _ abierto ( "in.txt" , Archivo :: omRead );

Pero es más conveniente abrir el archivo en el constructor: [1]

Archivo archivo ( "in.txt" , Archivo :: omRead );

Tipos de constructores

Una variedad de lenguajes de programación presentan varias variedades de constructores:

  • constructor con parámetros;
  • constructor por defecto que no acepta argumentos;
  • constructor nombrado - una función que asume una llamada explícita por nombre que funciona como un constructor
  • constructor de copia  : un constructor que toma como argumento un objeto de la misma clase (o una referencia de él);
  • constructor de conversión: un constructor que toma un argumento (estos constructores se pueden llamar automáticamente para convertir valores de otros tipos en objetos de esta clase).
  • move constructor ( específico de C++11 )
complejo de clase { público : // Constructor por defecto // (en este caso también un constructor de conversión) Complejo ( double i_re = 0 , double i_im = 0 ) : re ( i_re ), im ( i_im ) {} // Constructor de copias complejas ( const Complex & obj ) { re = objeto . re ; im = objeto . soy ; } privado : doble re , im ; };

Constructor con parámetros

Los constructores que toman uno o más argumentos se llaman parametrizados. Por ejemplo:

ejemplo de clase { int x , y ; público : ejemplo (); Ejemplo ( int a , int b ); // constructor parametrizado }; Ejemplo :: Ejemplo () { } Ejemplo :: Ejemplo ( int a , int b ) { x = un ; y = b ; }

Un constructor parametrizado se puede llamar explícita o implícitamente, por ejemplo:

Ejemplo e = Ejemplo ( 0 , 50 ); // llamada explicita Ejemplo e ( 0 , 50 ); // llamada implícita

Constructor por defecto

Un constructor sin argumentos requeridos. Se utiliza al crear matrices de objetos, llamados para crear cada instancia. En ausencia de un constructor predeterminado explícito, su código es generado por el compilador (que, por supuesto, no se refleja en el texto fuente).

Constructor con nombre

Copiar constructor

Un constructor cuyo argumento es una referencia a un objeto de la misma clase. Usado en C++ para pasar objetos a funciones por valor .

El constructor de copias se necesita principalmente cuando un objeto tiene punteros a objetos asignados en el montón . Si el programador no crea un constructor de copia, entonces el compilador creará un constructor de copia implícito que copia los punteros tal cual , es decir, no se produce una copia real de los datos y los dos objetos se refieren a los mismos datos en el montón. En consecuencia, un intento de cambiar la "copia" dañará el original, y llamar al destructor para uno de estos objetos, con el uso posterior del otro, conducirá al acceso a un área de memoria que ya no pertenece al programa.

El argumento debe pasarse por referencia , no por valor . Esto se deriva de una colisión: al pasar un objeto por valor (en particular, para llamar a un constructor), se requiere copiar el objeto. Pero para copiar un objeto, debe llamar al constructor de copia.

Constructor de conversión

Un constructor que toma un argumento. Especifica la conversión de tipo de su argumento al tipo del constructor. Esta conversión de tipo solo se aplica implícitamente si es única.

Una conversión de tipo definida por el usuario puede tomar una de dos formas: - de una clase tipo C a cualquier tipo T, para la cual C debe tener un C::operator T() - de cualquier tipo T a una clase tipo C, para la cual C debe tener C::C(T) (o C::C(T&), o C::C(T&&))

Si se permiten ambos casos en una expresión, se produce una ambigüedad y un error de compilación.

Si un constructor (u operador T()) está marcado con la palabra clave explícita, dicha conversión de tipo se aplica solo si hay una operación de conversión explícita de la forma (T)C o static_cast<T>C. Si no hay una palabra explícita, el compilador puede insertar tal conversión incluso implícitamente, por ejemplo, al llamar a la función f(T arg) en la forma f(C).

El constructor de movimientos

C ++ 11 introduce un nuevo tipo de referencias no constantes denominadas rvalue reference  y denotadas como T&&, y un nuevo tipo de constructor: move constructors .  El constructor de movimiento toma como entrada el valor de una referencia no constante a un objeto de clase y se usa para transferir la propiedad de los recursos de ese objeto. Los constructores de movimiento se inventaron para resolver la pérdida de eficiencia asociada con la creación de objetos temporales.

Constructor virtual

Un constructor no es virtual en el sentido de un método virtual  : para que el mecanismo de métodos virtuales funcione, debe ejecutar el constructor, que configurará automáticamente la tabla de métodos virtuales de este objeto.

"Constructores virtuales" se refiere a un mecanismo similar pero diferente que se encuentra en algunos lenguajes, como Delphi pero no C++ y Java . Este mecanismo le permite crear un objeto de cualquier clase previamente desconocida bajo dos condiciones:

  • esta clase es descendiente de alguna clase predefinida (en este ejemplo, es una clase TVehicle);
  • en toda la ruta de herencia desde la clase base hasta la creada, la cadena de redefinición no se rompió. Al anular un método virtual, la sintaxis de Delphi requiere la palabra clave overloadpara que puedan coexistir funciones antiguas y nuevas con diferentes firmas, overrideya sea para anular la función o reintroducepara definir una nueva función con el mismo nombre; esto último no está permitido.
tipo TVehicle = constructor de clase Create ; virtuales ; fin ; TAutomobile = clase ( TVehicle ) constructor Crear ; anular ; fin ; TMotorcycle = class ( TVehicle ) constructor Crear ; anular ; fin ; TMoped = class ( TMotorcycle ) // romper la cadena de redefinición - comenzar una nueva Crear constructor Crear ( x : entero ) ; reintroducir ; fin ;

Se introduce en el lenguaje el llamado tipo de clase ( metaclase ). Este tipo puede tomar como valor el nombre de cualquier clase derivada de TVehicle.

tipo CVehicle = clase de TVehicle ;

Este mecanismo le permite crear objetos de cualquier clase previamente desconocida derivada de TVehicle.

var cv : CVehículo ; v : TVehículo ; cv := TAutomóvil ; v := cv . crear ;

Observe que el código

cv := TMoped ; v := cv . crear ;

es incorrecto: la directiva ha reintroduceroto la cadena de anulación del método virtual y, de hecho, se llamará al constructor TMotorcycle.Create(lo que significa que se creará una motocicleta, ¡no un ciclomotor!)

Véase también Fábrica (patrón de diseño)

Sintaxis

C++

El nombre del constructor debe coincidir con el nombre de la clase. Se permiten múltiples constructores con el mismo nombre pero diferentes parámetros .

Ejemplo clase ClaseConConstructor { público : /* Inicializar objeto interno con constructor */ ClassWithConstructor ( parámetro flotante ) : objeto ( parámetro ) {} /* llamar al constructor AnotherClass(float); */ privado : Otro objeto de clase ; };

Pitón

En Python, un constructor es un método de clase llamado __init__. Además, no olvide que el primer argumento de cualquier método debe ser un puntero al contexto de la clase self.

Ejemplo clase ClaseConConstructor : def __init__ ( self ): """Este método es constructor.""" pasar

Rubí

El lenguaje Ruby usa un método especial para establecer un objeto en su estado consistente inicial initialize.

Ejemplo class ClassWithConstructor def initialize print 'Este método es constructor.' final final

Delfos

En Delphi , a diferencia de C++ , el constructor se declara con la palabra clave constructor. El nombre del constructor puede ser cualquier cosa, pero se recomienda nombrar el constructor Create.

Ejemplo TClassWithConstructor = constructor público de clase Create ; fin ;

Java

Algunas diferencias entre los constructores y otros métodos de Java :

  • los constructores no tienen un tipo de devolución (de hecho, siempre devuelven esto);
  • los constructores no se pueden llamar directamente (se debe usar la palabra clave new);
  • los constructores no pueden tener modificadores synchronized, final, y abstract;nativestatic
Ejemplo Ejemplo de clase pública { datos int privados ; // Constructor predeterminado, los datos se inicializan en 1 cuando se crea una instancia de la clase Example public Example () { data = 1 ; } // Sobrecarga de constructor public Ejemplo ( int input ) { data = input ; } } // código que ilustra la creación de un objeto por el constructor descrito anteriormente Ejemplo e = nuevo Ejemplo ( 42 );

JavaScript

En JavaScript , el constructor es una función normal que se usa como operando del operador new. La palabra clave se utiliza para referirse al objeto creado this.

Sin embargo, la especificación ECMAScript 6 agregó un contenedor sintáctico prototipo, que tiene propiedades de OOP como la herencia, así como una pequeña lista de métodos requeridos, por ejemplo: toString().

Ejemplo Ejemplo de función ( initValue ) { this . miValor = valorInicial ; } ejemplo _ prototipo _ getMyValue = función () { devuelve esto . miValor ; } // Ejemplo de clase de clase ES6 { constructor () { consola . registro ( 'constructor' ); } } // código que ilustra la creación de un objeto por el constructor descrito anteriormente var exampleObject = new Example ( 120 );

Visual Basic .NET

Los constructores en Visual Basic .NET usan un método de declaración regular llamado New.

Ejemplo Clase Foobar Private strData como cadena ' Constructor Public Sub New ( ByVal someParam As String ) strData = someParam End Sub End Class ' algún código ' que ilustra la creación de un objeto por parte del constructor Dim foo As New Foobar ( ".NET" ) arriba

C#

Ejemplo clase MiClase { private int _number ; cadena privada _cadena ; public MyClass ( int num , string str ) { _number = num ; _cadena = cadena ; } } // Código que ilustra la creación de un objeto por el constructor descrito anteriormente MyClass example = new MyClass ( 42 , "string" );

eiffel

En Eiffel , las rutinas que inicializan objetos se denominan procedimientos de creación . Los procedimientos de creación son algo similares a los de los constructores y algo diferentes. Tienen las siguientes características:

  • Los procedimientos de creación no tienen ningún tipo de resultado de retorno explícito (como se define en el procedimiento [Nota 1] ).
  • se nombran los procedimientos de creación (los nombres se limitan a identificadores válidos);
  • los procedimientos de creación se especifican mediante nombres en el texto de la clase;
  • los procedimientos de creación se pueden llamar directamente (como los procedimientos normales) para reinicializar objetos;
  • cada clase efectiva (es decir, concreta, no abstracta) debe (explícita o implícitamente) especificar al menos un procedimiento de creación;
  • los procedimientos de creación son responsables de llevar el objeto recién inicializado a un estado que satisfaga la invariante de clase [Nota 2] .

Aunque la creación de objetos está sujeta a algunas sutilezas [Nota 3] , la creación de un atributo con una declaración de tipo x: Texpresada como una declaración de creación create x.makeconsta de la siguiente secuencia de pasos:

  • crear una nueva instancia directa del tipo T[Nota 4] ;
  • ejecutar el procedimiento makede creación de la instancia recién creada;
  • adjunte el objeto recién creado a la entidad x.
Ejemplo

El primer pasaje a continuación define la clase POINT. El procedimiento makese codifica después de la palabra clave feature.

La palabra clave createpresenta una lista de procedimientos que se pueden usar para inicializar instancias de la clase. En este caso, la lista contiene default_createun procedimiento con una implementación vacía heredada de la clase ANYy un procedimiento makecon una implementación en la propia clase POINT.

clase PUNTO crear default_create , hacer rasgo make ( a_x_value : REAL ; a_y_value : REAL ) do x := a_x_value y := a_y_value end x : REAL -- Coordenada X y : REAL -- Coordenada Y ...

En el segundo pasaje, la clase que es el cliente de la clase POINTtiene declaraciones my_point_1de my_point_2tipo POINT.

En el código de la subrutina , se my_point_1crea con coordenadas (0.0; 0.0). Dado que no se especifica ningún procedimiento de creación en la sentencia de creación, se utiliza el procedimiento default_createheredado de la clase ANY. La misma línea podría reescribirse como create my_point_1.default_create. Solo los procedimientos especificados como procedimientos de creación se pueden usar en declaraciones de creación (es decir, declaraciones con la palabra clave create).

Luego viene la instrucción create for my_point_2, que establece los valores iniciales para las coordenadas my_point_2.

La tercera instrucción realiza una llamada de procedimiento normal makepara reinicializar la instancia adjunta my_point_2con diferentes valores.

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

Fusión en frío

Ejemplo

Cabe señalar que no existe un método constructor en ColdFusion . Un método común entre la comunidad de programación de ColdFusion es llamar al método ' ' initcomo un pseudoconstructor.

<cfcomponent displayname = "Cheese" > <!--- propiedades ---> <cfset variables . cheeseName = "" / > <!--- pseudo-constructor ---> <cffunction name = "init" returntype = "Cheese" > <cfargument name = "cheeseName" type = "string" required = "true" / > < variables cfset . quesoNombre = argumentos . cheeseName / > <cfreturn this / > </cffunction> </cfcomponent>

PHP

Ejemplo

En PHP (desde la versión 5), un constructor es un método __construct()que una palabra clave llama automáticamente newdespués de que se ha creado un objeto. Normalmente se utiliza para realizar varias inicializaciones automáticas, como la inicialización de propiedades. Los constructores también pueden tomar argumentos, en cuyo caso, cuando se especifica una expresión new, los parámetros formales deben pasarse al constructor entre paréntesis.

clase Persona { private $nombre ; function __construct ( $nombre ) { $esto -> nombre = $nombre ; } function getName () { return $this -> name ; } }

Sin embargo, un constructor en PHP versión 4 (y anteriores) es un método de clase con el mismo nombre de clase.

clase Persona { private $nombre ; function Persona ( $nombre ) { $esto -> nombre = $nombre ; } function getName () { return $this -> name ; } }

perl

Ejemplo

En Perl , el constructor debe aplicar la función bendecir a alguna variable (generalmente una referencia hash):

paquete Ejemplo ; sub new { mi $clase = shift ; mi $yo = {}; volver bendecir $auto , $clase ; } 1 ;

Pero esta es la opción básica mínima, hay muchos métodos más avanzados, que van desde campos de uso hasta Moose.

Constructores simplificados (con pseudocódigo )

Los constructores son siempre parte de la implementación de las clases. Una clase (en programación) describe las especificaciones de las características básicas del conjunto de objetos que son miembros de la clase, no las características individuales de ninguno de los objetos. Veamos una analogía simple. Tomemos como ejemplo un conjunto (o clase, para usar su significado más general) de estudiantes de cierta escuela. Así tenemos:

estudiante de clase { // descripción de la clase de estudiante // ... otro código ... }

Sin embargo, la clase Student es solo una plantilla general (prototipo) para nuestros estudiantes. Para usarlo, el programador crea a cada estudiante como un objeto o entidad ( implementación ) de la clase. Este objeto es ese dato real en la memoria cuyo tamaño, patrón, características y (hasta cierto punto) comportamiento están definidos por la definición de clase. La forma habitual de crear objetos es llamar a un constructor (las clases generalmente pueden tener constructores separados). Por ejemplo,

estudiante de clase { Estudiante(String nombreEstudiante, String Dirección, int ID) { // ... aquí almacenamos datos de entrada y otros campos internos ... } // ... }

Véase también

Notas

  1. ↑ Las subrutinas de Eiffel son procedimientos o funciones . Los procedimientos no tienen ningún tipo de retorno. Las funciones siempre tienen un tipo de retorno.
  2. Dado que el invariante de la(s) clase(s) heredada(s) también debe cumplirse, no existe un requisito obligatorio para llamar a los constructores principales.
  3. La especificación completa está contenida en los estándares ISO/ECMA para el lenguaje de programación Eiffel, disponible en línea. [2]
  4. El estándar Eiffel requiere que los campos se inicialicen la primera vez que se accede a ellos, incl. no es necesario inicializarlos con valores predeterminados en el momento de la creación del objeto.

Enlaces

  1. Por supuesto, esto conduce a ciertas dificultades técnicas; por ejemplo, ¿qué sucede si se lanza una excepción desde el constructor ? Sin embargo, el desarrollador de clases simplemente tiene que cumplir con los requisitos del lenguaje, y la mayoría de los programas no requieren diagnósticos detallados ni reintentos automáticos en caso de errores.
  2. Documento de descripción ISO/ECMA Eiffel . Consultado el 19 de abril de 2009. Archivado desde el original el 16 de junio de 2008.