Урок 22. Наследование. Часть 1

12 Мая 2023

Задача 22.1 📚

В методе можно просто вывести действие на консоль “издать звук” или “передвигаться”. 

Создайте базовый класс “Animal” и дочерний класс “Cat”. У класса “Animal” должны быть свойства “имя” и “возраст”, а также методы “издать звук” и “передвигаться”. Класс “Cat” должен наследовать эти свойства и методы, а также иметь свойство “тип шерсти”.

				
					class Animal {
	let name: String
	let age: Int
	
	init(name: String, age: Int) {
		self.name = name
		self.age = age
	}
	
	func makeSound() {
		print("The animal makes a sound")
	}
	
	func move() {
		print("The animal moves")
	}
}

class Cat: Animal {
	let furType: String
	
	init(name: String, age: Int, furType: String) {
		self.furType = furType
		super.init(name: name, age: age)
	}
}
				
			

Обратите внимание на то как располагаются элементы в классе:

1. Аутлеты

2. Публичные свойства 

3. Геттеры

4. Инициализаторы

5. Публичные методы класса

Этому расположению следует придерживаться. Подобная расстановка помогает искать нужный элемент, и легко ориентироваться в чужом коде. В дальнейшем этот список расширится. 

Публичные свойства и методы, это обычные свойства и методы, и в дальнейшем мы изучим еще несколько их разновидностей.

Все свойства в классах должны быть константами. 

Задача 22.2 📚

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

У вас есть словарь с данными:

				
					let data = ["name": "Бульбазавр",
			"image": "bulbasaur.jpg",
			"health": "8",
			"experience": "11"]
				
			

Создайте базовый класс “Character” и дочерний класс “Pokemon”. У класса “Character” должны быть свойства “health” и “experience” с типом Int. Класс “Pokemon” должен наследовать эти свойства, а также иметь свойства “name” и “image” с типом String. Инициализировать класс Pokemon необходимо данными из представленного словаря.

				
					let data = ["name": "Бульбазавр",
			"image": "bulbasaur.jpg",
			"health": "8",
			"experience": "11"]

class Character {
	let health: Int
	let experience: Int
	
	init(health: Int, experience: Int) {
		self.health = health
		self.experience = experience
	}
}

class Pokemon: Character {
	let name: String
	let image: String
	
	init(value: [String: String]) {
		name = value["name"] ?? ""
		image = value["image"] ?? ""
		
		let health = Int(value["health"] ?? "") ?? 0
		let experience = Int(value["experience"] ?? "") ?? 0
		super.init(health: health, experience: experience)
	}
}
				
			

Все свойства обоих классов должны быть константами. 

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

Давайте разберем следующую конструкцию:

				
					let health = Int(value["health"] ?? "") ?? 0
				
			

Вы наверняка знаете, что когда мы обращаемся по ключу к значению словаря value["health"], то нам возвращается опциональное значение, которое мы извлекаем при помощи значения по умолчанию.

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

Если вы не определяли дополнительных свойств для опциональных значений, то необходимо сносить длинные строки:

				
					init(value: [String: String]) {
		name = value["name"] ?? ""
		image = value["image"] ?? ""
		
		super.init(health: Int(value["health"] ?? "") ?? 0,
				   experience: Int(value["experience"] ?? "") ?? 0)
	}
				
			

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

				
					class Character {
	let health: Int?
	let experience: Int?
	
	init(health: Int?, experience: Int?) {
		self.health = health
		self.experience = experience
	}
}

class Pokemon: Character {
	let name: String?
	let image: String?
	
	init(value: [String: String]) {
		name = value["name"]
		image = value["image"]
		
		super.init(health: Int(value["health"] ?? ""),
				   experience: Int(value["experience"] ?? ""))
	}
}
				
			

Обратите внимание, что внутри приведения к типу Int все равно необходимо извлечь опциональное значение из значения словаря, иначе у вас будет двойной опционал. 

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

				
						init(value: [String: String]) {
		if let name = value["name"] {
			self.name = name
		}
		
		if let image = value["image"] {
			self.image = image
		}
		
		super.init(health: Int(value["health"] ?? "") ?? 0, // Ошибка 
				   experience: Int(value["experience"] ?? "") ?? 0)
	}
				
			

Компилятор выдаст вам ошибку, потому что появляется вероятность оставить свойства name и image не инициализированными, в том случае если по ключу мы не обнаружим значения, компилятор такого не может допустить, поэтому выдает ошибку. 

Если ваше решение отличается от представленных, отправьте его в телеграмм чат, получите личный фидбек.

Поддержите наш проект, и помогите изменить подход к обучению!

Развивайся вместе с нами

Поддержите наш проект, и помогите изменить подход к обучению!

Address List

Social Networks

Поддержите наш проект, и помогите изменить подход к обучению!