3. Добавьте конструкторы классов
В этом задании вы создадите конструктор для класса и продолжите работу со свойствами.
Шаг 1: Создайте конструктор
На этом шаге вы добавляете конструктор к Aquariumклассу, созданному в первом задании. В предыдущем примере каждый экземпляр класса Aquariumсоздается с одинаковыми размерами. Вы можете изменить размеры после создания, задав соответствующие свойства, но проще изначально создать экземпляр нужного размера.
В некоторых языках программирования, таких как Java, конструктор определяется путем создания метода внутри класса, имеющего то же имя, что и сам класс. В Kotlin конструктор определяется непосредственно в объявлении класса, указывая параметры в скобках, как если бы класс был методом. Как и в случае с функциями в Kotlin, эти параметры могут включать значения по умолчанию.
- В
Aquariumсозданном ранее классе измените определение класса, добавив три параметра конструктора со значениями по умолчанию дляlength,widthиheight, и присвойте их соответствующим свойствам.
class Aquarium(length: Int = 100, width: Int = 20, height: Int = 40) {
// Dimensions in cm
var length: Int = length
var width: Int = width
var height: Int = height
...
}
- Более компактный способ в Kotlin — определять свойства непосредственно в конструкторе, используя `getTetter`
varили `valsetTetter`, при этом Kotlin также автоматически создает геттеры и сеттеры. В этом случае можно удалить определения свойств в теле класса.
class Aquarium(var length: Int = 100, var width: Int = 20, var height: Int = 40) {
...
}
- При создании
Aquariumобъекта с помощью этого конструктора вы можете не указывать аргументы и получить значения по умолчанию, указать только некоторые из них или указать все и создать объект полностью пользовательского размераAquarium. ВbuildAquarium()функции попробуйте разные способы созданияAquariumобъекта с использованием именованных параметров.
fun buildAquarium() {
val aquarium1 = Aquarium()
aquarium1.printSize()
// default height and length
val aquarium2 = Aquarium(width = 25)
aquarium2.printSize()
// default width
val aquarium3 = Aquarium(height = 35, length = 110)
aquarium3.printSize()
// everything custom
val aquarium4 = Aquarium(width = 25, height = 35, length = 110)
aquarium4.printSize()
}
- Запустите программу и посмотрите на результат.
⇒ Width: 20 cm Length: 100 cm Height: 40 cm Width: 25 cm Length: 100 cm Height: 40 cm Width: 20 cm Length: 110 cm Height: 35 cm Width: 25 cm Length: 110 cm Height: 35 cm
Обратите внимание, что вам не пришлось перегружать конструктор и писать отдельную версию для каждого из этих случаев (плюс еще несколько для других комбинаций). Kotlin создает все необходимое из значений по умолчанию и именованных параметров.
Шаг 2: Добавьте блоки инициализации
Приведенные выше примеры конструкторов просто объявляют свойства и присваивают им значение выражения. Если вашему конструктору требуется больше кода инициализации, его можно разместить в одном или нескольких initблоках. На этом шаге вы добавляете несколько initблоков в Aquariumкласс.
- В
Aquariumкласс добавьтеinitблок для вывода информации о инициализации объекта и второйinitблок для вывода объема в литрах. Обратите внимание, чтоinitблоки могут содержать несколько операторов.
class Aquarium (var length: Int = 100, var width: Int = 20, var height: Int = 40) {
init {
println("aquarium initializing")
}
init {
// 1 liter = 1000 cm^3
println("Volume: ${width * length * height / 1000} liters")
}
...
}
- Запустите программу и посмотрите на результат.
aquarium initializing
Volume: 80 liters
Width: 20 cm Length: 100 cm Height: 40 cm
aquarium initializing
Volume: 100 liters
Width: 25 cm Length: 100 cm Height: 40 cm
aquarium initializing
Volume: 77 liters
Width: 20 cm Length: 110 cm Height: 35 cm
aquarium initializing
Volume: 96 liters
Width: 25 cm Length: 110 cm Height: 35 cm
Обратите внимание, что initблоки выполняются в том порядке, в котором они указаны в определении класса, и все они выполняются при вызове конструктора.
Шаг 3: Изучите вторичные конструкторы.
На этом шаге вы узнаете о вторичных конструкторах и добавите один в свой класс. Помимо основного конструктора, который может содержать один или несколько initблоков, класс Kotlin может также иметь один или несколько вторичных конструкторов. Эта особенность позволяет перегружать конструкторы, то есть создавать конструкторы с разными аргументами.
- В
Aquariumклассе добавьте дополнительный конструктор, который принимает в качестве аргумента количество рыб, используяconstructorключевое слово `require`. Создайтеvalсвойство `tark` для расчета объема аквариума в литрах в зависимости от количества рыб. Предположим, что на каждую рыбу приходится 2 литра (2000 см³) воды, плюс немного дополнительного места, чтобы вода не переливалась.
constructor(numberOfFish: Int) : this() {
// 2,000 cm^3 per fish + extra room so water doesn't spill
val tank = numberOfFish * 2000 * 1.1
}
- Внутри вторичного конструктора сохраните длину и ширину (заданные в основном конструкторе) неизменными и рассчитайте высоту, необходимую для придания резервуару заданного объема.
// calculate the height needed
height = (tank / (length * width)).toInt()
- В
buildAquarium()функции добавьте вызов для создания объектаAquariumс использованием вашего нового вторичного конструктора. Выведите размер и объем.
fun buildAquarium() {
val aquarium6 = Aquarium(numberOfFish = 29)
aquarium6.printSize()
println("Volume: ${aquarium6.width * aquarium6.length * aquarium6.height / 1000} liters")
}
- Запустите свою программу и посмотрите на результат.
⇒ aquarium initializing Volume: 80 liters Width: 20 cm Length: 100 cm Height: 31 cm Volume: 62 liters
Обратите внимание, что значение тома выводится дважды: один раз блоком кода initв основном конструкторе перед выполнением вторичного конструктора, и один раз кодом в buildAquarium().
Вы могли бы constructorтакже включить это ключевое слово в основной конструктор, но в большинстве случаев это не обязательно.
Шаг 4: Добавьте новый геттер свойства.
На этом шаге вы добавляете явный геттер свойства. Kotlin автоматически определяет геттеры и сеттеры при определении свойств, но иногда значение свойства необходимо скорректировать или вычислить. Например, выше вы вывели объем Aquarium. Вы можете сделать объем доступным в качестве свойства, определив для него переменную и геттер. Поскольку volumeзначение необходимо вычислить, геттер должен возвращать вычисленное значение, что можно сделать с помощью однострочной функции, которая сразу следует за именем и типом свойства .
- В
Aquariumклассе определитеIntсвойство с именем `<dependency>`volumeиget()метод, вычисляющий объем, в следующей строке.
val volume: Int
get() = width * height * length / 1000 // 1000 cm^3 = 1 liter
- Удалите
initблок, который печатает значение тома. - Удалите код,
buildAquarium()который выводит значение громкости. - В
printSize()метод добавьте строку для вывода объема.
fun printSize() {
println("Width: $width cm " +
"Length: $length cm " +
"Height: $height cm "
)
// 1 liter = 1000 cm^3
println("Volume: $volume liters")
}
- Запустите свою программу и посмотрите на результат.
⇒ aquarium initializing Width: 20 cm Length: 100 cm Height: 31 cm Volume: 62 liters
Размеры и объем остались прежними, но объем выводится только один раз после полной инициализации объекта как основным, так и вторичным конструктором.
Шаг 5: Добавьте сеттер свойства
На этом шаге вы создаёте новый метод установки свойств для тома.
- В
Aquariumклассе измените значениеvolumeнаvarтакое, чтобы его можно было установить несколько раз. - Добавьте метод-сеттер для
volumeсвойства, разместив егоset()ниже метода-геттера, который пересчитывает высоту на основе заданного количества воды. По соглашению, имя параметра-сеттера — `<setter>`value, но вы можете изменить его по своему усмотрению.
var volume: Int
get() = width * height * length / 1000
set(value) {
height = (value * 1000) / (width * length)
}
- Вставьте
buildAquarium()код, который установит объем аквариума на 70 литров. Выведите новый размер.
fun buildAquarium() {
val aquarium6 = Aquarium(numberOfFish = 29)
aquarium6.printSize()
aquarium6.volume = 70
aquarium6.printSize()
}
- Запустите программу еще раз и понаблюдайте за изменением высоты и объема.
⇒ aquarium initialized
Width: 20 cm Length: 100 cm Height: 31 cm
Volume: 62 liters
Width: 20 cm Length: 100 cm Height: 35 cm
Volume: 70 liters