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.
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 );Una variedad de lenguajes de programación presentan varias variedades de constructores:
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ícitaUn 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).
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.
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).
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.
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:
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)
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 ; };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.""" pasarEl 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 finalEn 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 ;Algunas diferencias entre los constructores y otros métodos de Java :
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 );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" ) arribaEn 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:
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:
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 ) ...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>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 ; } }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.
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 ... } // ... }