Kotlin конструктор с параметрами

Kotlin конструктор с параметрами

Для создания объекта необходимо вызвать конструктор класса. По умолчанию компилятор создает конструктор, который не принимает параметров и который мы можем использовать. Но также мы можем определять свои собственные конструкторы. Для определения конструкторов применяется ключевое слово constructor .

Классы в Kotlin могут иметь один первичный конструктор (primary constructor) и один или несколько вторичных конструкторов (secondary constructor).

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

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

class Person constructor(_name: String)

Конструкторы, как и обычные функции, могут иметь параметры. Так, в данном случае конструктор имеет параметр _name , который представляет тип String. Через параметры конструктора мы можем передать извне данные и использовать их для инициализации объекта. При этом первичный конструктор в отличие от функций не определяет никаких действий, он только может принимать данные извне через параметры.

Если первичный конструктор не имеет никаких аннотаций или модификаторов доступа, как в данном случае, то ключевое слово constructor можно опустить:

Инициализатор

Что делать с полученными через конструктор данными? Мы их можем использовать для инициализации свойств класса. Для этого применяются блоки инициализаторов:

В классе Person определено свойство name, которое хранит имя человека. Чтобы передать эту свойству значение параметра _name из первичного конструктора, применяется блок инициализатора. Блок инициализатора определяется после ключевого слова init .

Цель инициализатора состоит в инициализации объекта при его создании. Стоит отметить, что здесь свойству name не задается начальное значение, потому это свойство в любом случае будет инициализировано в блоке инициализатора, и при создании объекта оно в любом случае получит значение.

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

fun main() < val tom = Person("Tom") val bob = Person("Bob") val alice = Person("Alice") println(tom.name) // Tom println(bob.name) // Bob println(alice.name) // Alice >class Person(_name: String) < val name: String init< name = _name >>

Важно учитывать, что если мы определили первичный конструктор, то мы не можем использовать конструктор по умолчанию, который генерируется компилятором. Для создания объекта обязательно надо использовать первичный конструктор, если он определен в классе.

Стоит отметить, что в классе может быть определено одновременно несколько блоков инициализатора.

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

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

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

fun main() < val bob: Person = Person("Bob", 23) println("Name: $Age: $") > class Person(val name: String, var age: Int)

Свойства определяются как и параметры, при этом их определение начинается с ключевого слова val (если их не планируется изменять) и var (если свойства должны быть изменяемыми). И в этом случае нам уже необязательно явным образом определять эти свойства в теле класса, так как их уже определяет конструктор. И при вызове конструктора этим свойствам автоматически передаются значения: Person(«Bob», 23)

Читайте также:  Какие html коды у символов

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

Класс также может определять вторичные конструкторы. Они применяются в основном, чтобы определить дополнительные параметры, через которые можно передавать данные для инициализации объекта.

Вторичные конструкторы определяются в теле класса. Если для класса определен первичный конструктор, то вторичный конструктор должен вызывать первичный с помощью ключевого слова this :

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

И также добавлен вторичный конструктор. Он принимает два параметра: _name и _age. С помощью ключевого слова this вызывается первичный конструктор, поэтому через этот вызов необходимо передать значения для параметров первичного конструктора. В частности, в первичный конструктор передается значение параметра _name. В самом вторичном конструкторе устанавливается значение свойства age.

constructor(_name: String, _age: Int) : this(_name)

Таким образом, при вызове вторичного конструктора вначале вызывается первичный конструктор, срабатывает блок инициализатора, который устанавливает свойство name. Затем выполняются собственно действия вторичного конструктора, который устанавливает свойство age.

Используем данную модификацию класса Person:

fun main() < val tom: Person = Person("Tom") val bob: Person = Person("Bob", 45) println("Name: $Age: $") println("Name: $ Age: $") > class Person(_name: String) < val name: String = _name var age: Int = 0 constructor(_name: String, _age: Int) : this(_name)< age = _age >>

В функции main создаются два объекта Person. Для создания объекта tom применяется первичный конструктор, который принимает один параметр. Для создания объекта bob применяется вторичный конструктор с двумя параметрами.

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

Name: Tom Age: 0 Name: Bob Age: 45

При необходимости мы можем определять и больше вторичных конструкторов:

fun main() < val tom = Person("Tom") val bob = Person("Bob", 41) val sam = Person("Sam", 32, "JetBtains") println("Name: $Age: $ Company: $") println("Name: $ Age: $ Company: $") println("Name: $ Age: $ Company: $") > class Person(_name: String) < val name = _name var age: Int = 0 var company: String = "Undefined" constructor(_name: String, _age: Int) : this(_name)< age = _age >constructor(_name: String, _age: Int, _comp: String) : this(_name, _age) < company = _comp >>

Здесь в класс Person добавлено новое свойство — company , которое описывает компании, в которой работает человек. И также добавлен еще один конструктор, который принимает три параметра:

constructor(_name: String, _age: Int, _comp: String) : this(_name, _age)

Чтобы не дублировать код установки свойств name и age, этот вторичный конструктор передает установку этих свойств другому вторичному конструктору, который принимает два параметра, через вызов this(_name, _age) . То есть данный вызов по сути будет вызывать первый вторичный конструктор с двумя параметрами.

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

Name: Tom Age: 0 Company: Undefined Name: Bob Age: 41 Company: Undefined Name: Sam Age: 32 Company: JetBtains

Источник

Классы

Классы в Kotlin объявляются с помощью использования ключевого слова class .

Объявление класса состоит из имени класса, заголовка (указания типов его параметров, основного конструктора и т.п) и тела класса, заключённого в фигурные скобки. И заголовок, и тело класса являются необязательными составляющими. Если у класса нет тела, фигурные скобки могут быть опущены.

Читайте также:  Apache mod php enable

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

Класс в Kotlin может иметь основной конструктор (primary constructor) и один или более дополнительных конструкторов (secondary constructors). Основной конструктор является частью заголовка класса, его объявление идёт сразу после имени класса (и необязательных параметров).

class Person constructor(firstName: String) < /*. */ >

Если у основного конструктора нет аннотаций и модификаторов видимости, ключевое слово constructor может быть опущено.

class Person(firstName: String) < /*. */ >

Основной конструктор не может содержать в себе исполняемого кода. Инициализирующий код может быть помещён в соответствующие блоки (initializers blocks), которые помечаются словом init .

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

class InitOrderDemo(name: String) < val firstProperty = "Первое свойство: $name".also(::println) init < println("Первый блок инициализации: $") > val secondProperty = "Второе свойство: $".also(::println) init < println("Второй блок инициализации: $") > > 

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

class Customer(name: String)

Для объявления и инициализации свойств основного конструктора в Kotlin есть лаконичное синтаксическое решение:

class Person(val firstName: String, val lastName: String, var age: Int) 

Такие объявления также могут включать в себя значения свойств класса по умолчанию.

class Person(val firstName: String, val lastName: String, var isEmployed: Boolean = true) 

Вы можете использовать завершающую запятую при объявлении свойств класса.

class Person( val firstName: String, val lastName: String, var age: Int, // завершающая запятая ) < /*. */ >

Свойства, объявленные в основном конструкторе, могут быть изменяемые ( var ) и неизменяемые ( val ).

Если у конструктора есть аннотации или модификаторы видимости, ключевое слово constructor обязательно, и модификаторы используются перед ним.

class Customer public @Inject constructor(name: String) < /*. */ >

Для более подробной информации см. «Модификаторы доступа».

Дополнительные конструкторы

В классах также могут быть объявлены дополнительные конструкторы (secondary constructors), перед которыми используется ключевое слово constructor .

class Person(val pets: MutableList = mutableListOf()) class Pet < constructor(owner: Person) < owner.pets.add(this) // добавляет этого питомца в список домашних животных своего владельца >> 

Если у класса есть основной конструктор, каждый дополнительный конструктор должен прямо или косвенно ссылаться (через другой(ие) конструктор(ы)) на основной. Осуществляется это при помощи ключевого слова this .

class Person(val name: String) < val children: MutableList= mutableListOf() constructor(name: String, parent: Person) : this(name) < parent.children.add(this) >> 

Обратите внимание, что код в блоках инициализации фактически становится частью основного конструктора. Дополнительный конструктор ссылается на основной при помощи своего первого оператора, поэтому код во всех блоках инициализации, а также инициализация свойств выполняется перед выполнением кода в теле дополнительного конструктора.

Читайте также:  Переходим на сайт суперпродукт.ru

Даже если у класса нет основного конструктора на него все равно происходит неявная ссылка и блоки инициализации выполняются также.

class Constructors < init < println("Блок инициализации") >constructor(i: Int) < println("Constructor $i") >> 

Если в абстрактном классе не объявлено никаких конструкторов (основного или дополнительных), у этого класса автоматически сгенерируется пустой конструктор без параметров. Видимость этого конструктора будет public.

Если вы не желаете иметь класс с открытым public конструктором, вам необходимо объявить пустой конструктор с соответствующим модификатором видимости.

class DontCreateMe private constructor () < /*. */ >

On the JVM, if all of the primary constructor parameters have default values, the compiler will generate an additional parameterless constructor which will use the default values. This makes it easier to use Kotlin with libraries such as Jackson or JPA that create class instances through parameterless constructors. > > «`kotlin > class Customer(val customerName: String = «») > «` —>

В JVM компилятор генерирует дополнительный конструктор без параметров в случае, если все параметры основного конструктора имеют значения по умолчанию. Это делает использование таких библиотек, как Jackson и JPA, более простым с Kotlin, так как они используют пустые конструкторы при создании экземпляров классов.

class Customer(val customerName: String = "") 

Создание экземпляров классов

Для создания экземпляра класса конструктор вызывается так, как если бы он был обычной функцией.

val invoice = Invoice() val customer = Customer("Joe Smith") 

В Kotlin нет ключевого слова new .

Создание экземпляров вложенных, внутренних и анонимных внутренних классов описано в разделе Вложенные классы.

Члены класса

Классы могут содержать в себе:

Наследование

Классы могут быть производными друг от друга и формировать иерархии наследования. Узнайте больше о наследовании в Котлине.

Абстрактные классы

Класс может быть объявлен как abstract со всеми или некоторыми его членами. Абстрактный член не имеет реализации в своём классе. Обратите внимание, что нам не надо аннотировать абстрактный класс или функцию словом open — это и так подразумевается.

abstract class Polygon < abstract fun draw() >class Rectangle : Polygon() < override fun draw() < // рисование прямоугольника >> 

Можно переопределить неабстрактный open член абстрактным.

open class Polygon < open fun draw() < // некоторый метод рисования полигонов по умолчанию >> abstract class WildShape : Polygon() < // Классы, которые наследуют WildShape, должны предоставлять свой собственный // метод рисования вместо использования по умолчанию для полигона abstract override fun draw() >

Вспомогательные объекты

Если вам нужно написать функцию, которая может быть использована без создания экземпляра класса, имеющую доступ к данным внутри этого класса (к примеру, фабричный метод), вы можете написать её как член объявления объекта внутри этого класса.

В частности, если вы объявляете вспомогательный объект в своём классе, у вас появляется возможность обращаться к членам класса, используя только название класса в качестве классификатора.

© 2015—2023 Open Source Community

Источник

Оцените статью