В объектно-ориентированном программировании конструктор класса (от англ. constructor, иногда сокращают ctor) — специальный блок инструкций, вызываемый при создании объекта.
Конструктор схож с методом, но отличается от метода тем, что не имеет явным образом определённого типа возвращаемых данных, не наследуется, и обычно имеет различные правила для рассматриваемых модификаторов. Конструкторы часто выделяются наличием одинакового имени с именем класса, в котором объявляется. Их задача — инициализировать члены объекта и определить инвариант класса, сообщив в случае некорректности инварианта. Корректно написанный конструктор оставит объект в «правильном» состоянии. Неизменяемые объекты тоже должны быть проинициализированы конструктором.
Термин «конструктор» также используется для обозначения одного из тегов, описывающих данные в алгебраическом типе данных. Это использование несколько отличается от описываемого в статье. Для дополнительной информации смотрите Алгебраический тип данных.
В большинстве языков конструктор может быть перегружен, что позволяет использовать несколько конструкторов в одном классе, причём каждый конструктор может иметь различные параметры.
Содержание |
Одна из ключевых особенностей ООП — инкапсуляция: внутренние поля объекта напрямую недоступны, и пользователь может работать с объектом только как с единым целым, через открытые (public
) методы. Каждый метод, в идеале, должен быть устроен так, чтобы объект, находящийся в «допустимом» состоянии (то есть когда выполняется инвариант класса), после вызова метода также оказался в допустимом состоянии. И первая задача конструктора — перевести поля объекта в такое состояние.
Вторая задача — упростить пользование объектом. Объект — не «вещь в себе», ему часто приходится требовать какую-то информацию от других объектов: например, объект File
, создаваясь, должен получить имя файла. Это можно сделать и через метод:
File file; file.open("in.txt", File::omRead);
Но удобнее открытие файла сделать в конструкторе:[1]
File file("in.txt", File::omRead);
Некоторые языки программирования различают несколько особых типов конструкторов:
class Complex { public: // Конструктор по умолчанию // (в данном случае является также и конструктором преобразования) Complex(double i_re = 0, double i_im = 0) : re(i_re), im(i_im) {} // Конструктор копирования Complex(const Complex &obj) { re = obj.re; im = obj.im; } private: double re, im; };
Конструктор не имеющий обязательных аргументов. Используется при создании массивов объектов, вызываясь для создания каждого экземпляра. В отсутствие явно заданного конструктора по умолчанию его код генерируется компилятором (что на исходном тексте, естественно, не отражается).
Конструктор, аргументом которого является ссылка на объект того же класса. Применяется в C++ для передачи объектов в функции по значению.
Конструктор копирования в основном необходим, когда объект имеет указатели на объекты выделенные в куче. Если программист не создаёт конструктор копирования, то компилятор создаст неявный конструктор копирования, который копирует указатели как есть, то есть фактическое копирование данных не происходит и два объекта ссылаются на одни и те же данные в куче. Соответственно попытка изменения «копии» повредит оригинал, а вызов деструктора для одного из этих объектов при последующем использовании другого приведёт к обращению в область памяти, уже не принадлежащую программе.
Аргумент должен передаваться именно по ссылке, а не по значению. Это вытекает из коллизии: при передаче объекта по значению (в частности, для вызова конструктора) требуется скопировать объект. Но для того, чтобы скопировать объект, необходимо вызвать конструктор копирования.
Конструктор, принимающий один аргумент. Задаёт преобразование типа своего аргумента в тип конструктора. Такое преобразование типа неявно применяется только если оно уникально.
Конструктор не бывает виртуальным в смысле виртуального метода — для того, чтобы механизм виртуальных методов работал, нужно запустить конструктор, который автоматически настроит таблицу виртуальных методов данного объекта.
«Виртуальными конструкторами» называют похожий, но другой механизм, присутствующий в некоторых языках — например, он есть в Delphi, но нет в C++ и Java. Этот механизм позволяет создать объект любого заранее неизвестного класса при двух условиях:
TVehicle
);overload
, чтобы старая и новая функции с разными сигнатурами могли сосуществовать, override
для переопределения функции либо reintroduce
для задания новой функции с тем же именем — последнее недопустимо.type TVehicle = class constructor Create; virtual; end; TAutomobile = class (TVehicle) constructor Create; override; end; TMotorcycle = class (TVehicle) constructor Create; override; end; TMoped = class (TMotorcycle) // обрываем цепочку переопределения - заводим новый Create constructor Create(x : integer); reintroduce; end;
В языке вводится так называемый классовый тип (метакласс). Этот тип в качестве значения может принимать название любого класса, производного от TVehicle
.
type CVehicle = class of TVehicle;
Такой механизм позволяет создавать объекты любого заранее неизвестного класса, производного от TVehicle
.
var cv : CVehicle; v : TVehicle; cv := TAutomobile; v := cv.Create;
Заметьте, что код
cv := TMoped; v := cv.Create;
является некорректным — директива reintroduce
разорвала цепочку переопределения виртуального метода, и в действительности будет вызван конструктор TMotorcycle.Create
(а значит, будет создан мотоцикл, а не мопед!)
См. также Фабрика (шаблон проектирования)
Имя конструктора должно совпадать с именем класса. Допускается использовать несколько конструкторов с одинаковым именем, но различными параметрами.
class ClassWithConstructor { public: /* Инициализация внутреннего объекта с помощью конструктора */ ClassWithConstructor(float parameter): object(parameter) {}/* вызов конструктора AnotherClass(float); */ private: AnotherClass object; };
В языке Python конструктором является метод класса с именем __init__ . Кроме того не следует забывать, что первым аргументом любого метода должен быть указатель на контекст класса self.
class ClassWithConstructor: def __init__(self): """This method is constructor.""" pass
В Delphi, в отличие от C++, для объявления конструктора служит ключевое слово constructor
. Имя конструктора может быть любым, но рекомендуется называть конструктор Create
.
TClassWithConstructor = class public constructor Create; end;
Некоторые отличия между конструкторами и другими методами Java:
new
);synchronized
, final
, abstract
, native
и static
типов;public class Example { // Конструктор по умолчанию public Example() { this(1); } // Перегрузка конструктора public Example(int input) { data = input; } private int data; }
// код, иллюстрирующий создание объекта описанным выше конструктором Example e = new Example(42);
В JavaScript в качестве конструктора выступает обычная функция, используемая в качестве операнда оператора new
. Для обращения к созданному объекту используется ключевое слово this
.
function Example(initValue) { this.myValue = initValue; } Example.prototype.getMyValue = function() { return this.myValue; }
// код, иллюстрирующий создание объекта описанным выше конструктором var exampleObject = new Example(120);
Конструкторы в Visual Basic .NET используют обычный метод объявления с именем New
.
Class Foobar Private strData As String ' Constructor Public Sub New(ByVal someParam As String) strData = someParam End Sub End Class
' некий код ' иллюстрирующий создание объекта описанным выше конструктором Dim foo As New Foobar(".NET")
class myClass { private int mA; private string mB; public myClass(int a, string b) { mA = a; mB = b; } }
// код, иллюстрирующий создание объекта описанным выше конструктором myClass c = new myClass(42, "string");
В Эйфеле подпрограммы, которые инициализируют объекты, называются процедурами создания. Процедуры создания в чём-то подобны конструкторам и в чём-то отличаются. Они имеют следующие характеристики:
Хотя создание объекта является предметом некоторых тонкостей [Примечание 3], создание атрибута с типовым объявлением x: T
, выраженном в виде инструкции создания create x.make
состоит из следующей последовательности шагов:
T
[Примечание 4];make
для вновь созданного экземпляра;x
.В первом отрывке ниже определяется класс POINT
. Процедура make
кодируется после ключевого слова feature
.
Ключевое слово create
вводит список процедур, которые могут быть использованы для инициализации экземпляров класса. В данном случае список содержит default_create
, процедуру с пустой реализацией, унаследованной из класса ANY
, и процедуру make
с реализацией в самом классе POINT
.
class POINT create default_create, make feature make (a_x_value: REAL; a_y_value: REAL) do x := a_x_value y := a_y_value end x: REAL -- Координата X y: REAL -- Координата Y ...
Во втором отрывке класс, являющийся клиентом класса POINT
, имеет объявления my_point_1
и my_point_2
типа POINT
.
В коде подпрограммы my_point_1
создаётся с координатами (0.0; 0.0). Поскольку в инструкции создания не указана процедура создания, используется процедура default_create
, унаследованная из класса ANY
. Эта же строка могла бы быть переписана как create my_point_1.default_create
. Только процедуры, указанные как процедуры создания могут использоваться в инструкциях создания (то есть в инструкциях с ключевым словом create
).
Следующей идёт инструкция создания для my_point_2
, задающая начальные значения для координат my_point_2
.
Третья инструкция осуществляет обычный вызов процедуры make
для ре-инициализации экземпляра, прикреплянного к my_point_2
, другими значениями.
my_point_1: POINT my_point_2: POINT ... create my_point_1 create my_point_2.make (3.0, 4.0) my_point_2.make (5.0, 8.0) ...
Необходимо отметить, что в ColdFusion не существует метода-конструктора. Широкое распространение среди сообщества программистов на ColdFusion получил способ вызова метода 'init
', выступающего в качестве псевдоконструктора.
<cfcomponent displayname="Cheese"> <!--- свойства ---> <cfset variables.cheeseName = "" /> <!--- псевдоконструктор ---> <cffunction name="init" returntype="Cheese"> <cfargument name="cheeseName" type="string" required="true" /> <cfset variables.cheeseName = arguments.cheeseName /> <cfreturn this /> </cffunction> </cfcomponent>
В PHP (начиная с версии 5) конструктор — это метод __construct()
, который автоматически вызывается ключевым словом new
после создания объекта. Обычно используется для выполнения различных автоматических инициализаций, как например, инициализация свойств. Конструкторы также могут принимать аргументы, в этом случае, когда указано выражение new
, необходимо передать конструктору формальные параметры в круглых скобках.
class Person { private $name; function __construct($name) { $this->name = $name; } function getName() { return $this->name; } }
Тем не менее, конструктор в PHP версии 4 (и ранее) — метод класса с именем этого же класса.
class Person { private $name; function Person($name) { $this->name = $name; } function getName() { return $this->name; } }
Конструкторы всегда являются частью реализации классов. Класс (в программировании) описывает спецификации основных характеристик набора объектов, являющихся членами класса, а не отдельные характеристики какого-либо объекта из них. Рассмотрим простую аналогию. Возьмем в качестве примера набор (или класс, используя его более общее значение) учеников некоторой школы. Таким образом мы имеем:
class Student { // описание класса учеников // ... прочий код ... }
Тем не менее, класс Student
— всего лишь общий шаблон (прототип) наших школьников. Для его использования программист создает каждого школьника в виде объекта или сущности (реализации) класса. Этот объект является тем реальным фрагментом данных в памяти, чьи размер, шаблон, характеристики и (в некоторой мере) поведение определяются описанием класса. Обычный способ создания объектов — вызов конструктора (классы в общем случае могут иметь отдельные конструкторы). Например,
class Student { Student (String studentName, String Address, int ID) { // ... здесь храним вводимые данные и прочие внутрнние поля ... } // ... }
Это заготовка статьи о программировании. Вы можете помочь проекту, исправив и дополнив её. |
Конструктор (программирование).