Конструктор (объектно-ориентированное программирование)В объектно-ориентированном программировании конструктор класса (от англ. constructor) — специальный блок инструкций, вызываемый при создании объекта. Назначение конструктора
Одна из ключевых особенностей ООП — инкапсуляция: внутренние поля класса напрямую недоступны, и пользователь может работать с объектом только как с единым целым, через открытые ( Вторая задача — упростить пользование объектом. Объект — не «вещь в себе», ему часто приходится требовать какую-то информацию от других объектов: например, объект 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;
};
Конструктор с параметрамиКонструкторы, принимающие один или более аргументов, называются параметризованными. Например: class Example
{
int x, y;
public:
Example();
Example(int a, int b); // параметризованный конструктор
};
Example :: Example()
{
}
Example :: Example(int a, int b)
{
x = a;
y = b;
}
Параметризованный конструктор может быть вызван явно или неявно, например: Example e = Example(0, 50); // явный вызов
Example e(0, 50); // неявный вызов
Конструктор по умолчаниюКонструктор, не имеющий обязательных аргументов. Используется при создании массивов объектов, вызываясь для создания каждого экземпляра. В отсутствие явно заданного конструктора по умолчанию его код генерируется компилятором (что на исходном тексте, естественно, не отражается). Именованный конструктор
Конструктор копированияКонструктор, аргументом которого является ссылка на объект того же класса. Применяется в C++ для передачи объектов в функции по значению. Конструктор копирования в основном необходим, когда объект имеет указатели на объекты, выделенные в куче. Если программист не создаёт конструктор копирования, то компилятор создаст неявный конструктор копирования, который копирует указатели как есть, то есть фактическое копирование данных не происходит и два объекта ссылаются на одни и те же данные в куче. Соответственно попытка изменения «копии» повредит оригинал, а вызов деструктора для одного из этих объектов при последующем использовании другого приведёт к обращению в область памяти, уже не принадлежащую программе. Аргумент должен передаваться именно по ссылке, а не по значению. Это вытекает из коллизии: при передаче объекта по значению (в частности, для вызова конструктора) требуется скопировать объект. Но для того, чтобы скопировать объект, необходимо вызвать конструктор копирования. Конструктор преобразованияКонструктор, принимающий один аргумент. Задаёт преобразование типа своего аргумента в тип конструктора. Такое преобразование типа неявно применяется только если оно уникально. Определенное пользователем преобразование типа может иметь одну из двух форм: - из классового типа C в любой тип T, для чего у С должен быть C::operator T() - из любого типа T в классовый тип C, для чего у C должен быть C::C(T) (или же C::C(T&), или же C::C(T&&)) Если в каком-то выражении допустимы оба этих случая, возникает неоднозначность и ошибка компиляции. Если конструктор (или operator T()) помечен ключевым словом explicit, то такое преобразование типа применяется только при наличии явной операции приведения типа вида (T)C или же static_cast<T>C. Если же слова explicit нет, то компилятор может вставить такое преобразование даже неявно, например, при вызове функции f(T arg) в виде f(C). Конструктор перемещенияВ C++11 появился новый тип неконстантных ссылок, носящий название «ссылка на праводопустимое выражение» (англ. rvalue reference) и обозначаемый как Виртуальный конструкторКонструктор не бывает виртуальным в смысле виртуального метода — для того, чтобы механизм виртуальных методов работал, нужно запустить конструктор, который автоматически настроит таблицу виртуальных методов данного объекта. «Виртуальными конструкторами» называют похожий, но другой механизм, присутствующий в некоторых языках — например, он есть в Delphi, но нет в C++ и Java. Этот механизм позволяет создать объект любого заранее неизвестного класса при двух условиях:
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;
В языке вводится так называемый классовый тип (метакласс). Этот тип в качестве значения может принимать название любого класса, производного от type
CVehicle = class of TVehicle;
Такой механизм позволяет создавать объекты любого заранее неизвестного класса, производного от var
cv : CVehicle;
v : TVehicle;
cv := TAutomobile;
v := cv.Create;
Заметьте, что код cv := TMoped;
v := cv.Create;
является некорректным — директива См. также Фабрика (шаблон проектирования) СинтаксисC++Имя конструктора должно совпадать с именем класса. Допускается использовать несколько конструкторов с одинаковым именем, но различными параметрами. Примерclass ClassWithConstructor {
public:
/* Инициализация внутреннего объекта с помощью конструктора */
ClassWithConstructor(float parameter): object(parameter) {}/* вызов конструктора AnotherClass(float); */
private:
AnotherClass object;
};
PythonВ языке Python конструктор состоит из двух методов класса: Примерclass ClassWithConstructor:
def __new__(cls):
"""This method is the first part of the constructor."""
return super().__new__(cls)
def __init__(self):
"""This method is the second part of the constructor."""
pass
RubyВ языке Ruby, чтобы задать объекту первоначальное непротиворечивое состояние, используется специальный метод Примерclass ClassWithConstructor
def initialize
print 'This method is constructor.'
end
end
DelphiВ Delphi, в отличие от C++, для объявления конструктора служит ключевое слово Пример TClassWithConstructor = class
public
constructor Create;
end;
JavaНекоторые отличия между конструкторами и другими методами Java:
Примерpublic class Example {
private int data;
// Конструктор по умолчанию, data инициализируется 1, при создании экземпляра класса Example
public Example() {
data = 1;
}
// Перегрузка конструктора
public Example(int input) {
data = input;
}
}
// код, иллюстрирующий создание объекта описанным выше конструктором
Example e = new Example(42);
JavaScriptВ JavaScript в качестве конструктора выступает обычная функция, используемая в качестве операнда оператора Однако в спецификации ECMAScript 6 были добавлена синтаксическая оболочка прототипов, которой присущи такие свойства ООП как наследование, а также небольшой список обязательных методов, например: Примерfunction Example(initValue) {
this.myValue = initValue;
}
Example.prototype.getMyValue = function() {
return this.myValue;
}
//ES6 class
class Example {
constructor() {
console.log('constructor');
}
}
// код, иллюстрирующий создание объекта описанным выше конструктором
var exampleObject = new Example(120);
Visual Basic .NETКонструкторы в Visual Basic .NET используют обычный метод объявления с именем Пример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")
C#Примерclass MyClass
{
private int _number;
private string _string;
public MyClass(int num, string str)
{
_number = num;
_string = str;
}
}
// Код, иллюстрирующий создание объекта описанным выше конструктором
MyClass example = new MyClass(42, "string");
ЭйфельВ Эйфеле подпрограммы, которые инициализируют объекты, называются процедурами создания. Процедуры создания в чём-то подобны конструкторам и в чём-то отличаются. Они имеют следующие характеристики:
Хотя создание объекта является предметом некоторых тонкостей [Примечание 3], создание атрибута с типовым объявлением
ПримерВ первом отрывке ниже определяется класс Ключевое слово 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
...
Во втором отрывке класс, являющийся клиентом класса В коде подпрограммы Следующей идёт инструкция создания для Третья инструкция осуществляет обычный вызов процедуры 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 не существует метода-конструктора. Широкое распространение среди сообщества программистов на ColdFusion получил способ вызова метода ' <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ПримерВ PHP (начиная с версии 5) конструктор — это метод 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;
}
}
PerlПримерВ Perl конструктор должен применить функцию bless к некой переменной (обычно ссылке на хеш): package Example;
sub new {
my $class = shift;
my $self = {};
return bless $self, $class;
}
1;
Но это минимальный базовый вариант, есть множество более продвинутых способов, начиная от use fields и заканчивая Moose. Упрощенные конструкторы (с псевдокодом)Конструкторы всегда являются частью реализации классов. Класс (в программировании) описывает спецификации основных характеристик набора объектов, являющихся членами класса, а не отдельные характеристики какого-либо объекта из них. Рассмотрим простую аналогию. Возьмем в качестве примера набор (или класс, используя его более общее значение) учеников некоторой школы. Таким образом мы имеем: class Student {
// описание класса учеников
// ... прочий код ...
}
Тем не менее, класс class Student {
Student (String studentName, String Address, int ID) {
// ... здесь храним вводимые данные и прочие внутрнние поля ...
}
// ...
}
См. такжеПримечания
Ссылки
|
Portal di Ensiklopedia Dunia