Конструкторы

Последнее обновление: 11.12.2023

Для создания объекта класса необходим вызов конструктора. Есть два типа конструкторов: первичные или основные и вторичные или дополнительные.

Первичный конструктор

Каждый класс имеет один первичный конструктор. Как и обычная функция, конструктор может иметь параметры. Например:

type Person() = do printfn "Создание объекта класса Person"

let tom = Person()

Перечисление параметров идет в скобках после имени класса. В примере выше параметры не используются, поэтому после имени класса указаны пустые скобки. Теперь определим пару параметров:

type Person (name, age) = 
    do printfn $"Person name: {name}  age: {age}"


let tom = Person("Tom", 37)
let bob = Person("Bob", 41)

Здесь первичный конструктор имеет два параметра: name и age. Параметры определяются в скобках через запятую. При вызове конструктора мы должны передать ему значения для его параметров.

Стоит отметить, что в определении класса после знака равно (=) фактически идут действия, выполняемые первичным конструктором. Поэтому мы можем обратиться к значениям параметров:

do printfn $"Person name: {name}  age: {age}"

Результат работы программы:

Person name: Tom  age: 37
Person name: Bob  age: 41

При этом параметры конструктора также можно типизировать, а при вызове конструктора передавать параметрам значения по имени:

type Person (name: string, age: int) = 
    do printfn $"Person name: {name}  age: {age}"

let tom = Person("Tom", 37)					// передача значений параметрам по позиции
let sam = Person(age = 24, name= "Sam")		// передача значений параметрам по имени

Вторичные конструкторы

Класс может иметь только один первичный конструктор. Но в дополнение к нему можно определить несколько вторичных конструкторов. Они определяются с помощью ключевого слова new. Вторичный конструктор должен вызывать первичный. Например, определим вторичный конструктор в классе Person:

type Person (name, age) = 
    do printfn $"Person name: {name}  age: {age}"
    new() = Person("Undefined", 1)

let tom = Person("Tom", 37)
let bob = Person()

Строка

new() = Person("Undefined", 1)

представляет определение вторичного конструктора - оно начинается с ключевого слова new, после которого в скобках идут параметры этого конструктора. В данном случае вторичный конструктор не имеет параметров. После знака равно идет вызов первичного конструктора. Вызов первичного конструктора представляет имя класса, после которого в скобках передаются значения для параметров первичного конструктора. То есть фактически также, как мы создаем объект класса.

Поскольку мы определили второй конструктор, мы можем его использовать для создания объекта класса Person:

let bob = Person()

В данном случае будет выполняться вызов Person("Undefined", 1).

Консольный вывод программы:

Person name: Tom  age: 37
Person name: Undefined  age: 1

Вторичных конструкторов может быть множество. Так, добавим еще один вторичный конструктор:

type Person (name, age) = 
    do printfn $"Person name: {name}  age: {age}"
    new() = Person("Undefined", 1)
    new(name) = Person(name, 1)

let tom = Person("Tom", 37) // вызов первичного конструктора
let bob = Person()           // вызов первого вторичного конструктора
let sam = Person("Sam")     // вызов второго вторичного конструктора

Здесь добавлен второй вторичный конструктор, который принимает один параметр:

new(name) = Person(name, 1)

Он также вызывает первичный конструктор, только его первому параметру передает значение своего единственного параметра.

После этого мы также сможем использовать этот конструктор для создания объектов:

let sam = Person("Sam") 

Консольный вывод программы:

Person name: Tom  age: 37
Person name: Undefined  age: 1
Person name: Sam  age: 1

Цепочка вызовов конструкторов

Выше в примере оба вторичных конструктора вызывали первичный, однако они также могут вызывать и один из вторичных конструкторов, главное, чтобы цепочка вызовов конструкторов в конечном счете привела к вызову первичного конструктора:

type Person (name, age) = 
    do printfn $"Person name: {name}  age: {age}"
    new(name) = Person(name, 1)     // вызываем первичный конструктор
    new() = Person("Undefined")     // вызываем первый вторичный конструктор

Таким образом, создания объекта:

let bob = Person()

Приведет к вызову вторичного конструктора

new() = Person("Undefined") 

Который вызовет другой вторичный конструктор:

new(name) = Person(name, 1) 

А этот вызов, в свою очередь, приведет к вызову первичного конструктора.

Определение действий во вторичном конструкторе

Выше мы увидели, как вызывать некоторые действия в первичном конструкторе (с помощью выражения do), но что, если мы хотим также определить некоторые действия во вторичном конструкторе? В этом случае используется выражение then:

type Person (name, age) = 
    do printfn $"Person name: {name}  age: {age}"

    new(name) =             // определение вторичного конструтора
        Person(name, 1) 
        then                // действия выполняемые во вторичном конструкторе
            printfn $"Для name передано значение: {name}"
            printfn $"Для age будет передано значение: 1"
    
    new() = Person("Undefined")

let sam = Person("Sam")     // вызов второго вторичного конструктора

Теперь первый вторичный конструктор выглядит следующим образом:

new(name) =             // определение вторичного конструтора
	Person(name, 1) 
	then                // действия выполняемые во вторичном конструкторе
		printfn $"Для name передано значение: {name}"
		printfn $"Для age будет передано значение: 1"

После оператора then помещаются все дополнительные действия, выполняемые этим конструктором.

Консольный вывод программы:

Person name: Sam  age: 1
Для name передано значение: Sam
Для age будет передано значение: 1
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850