Menu
CoddyTech

Цепочки наследования

Часть раздела Объектно-ориентированное программирование путешествия по GDScript на Coddy. Урок 18 из 65.

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

# vehicle.gd
class_name Vehicle
extends RefCounted

var wheels: int

func _init(w: int) -> void:
	wheels = w

func describe() -> String:
	return "%d wheels" % wheels
# car.gd
class_name Car
extends Vehicle

func _init() -> void:
	super(4)

func describe() -> String:
	return "Car with " + super()
# race_car.gd
class_name RaceCar
extends Car

var top_speed: int

func _init(speed: int) -> void:
	super()
	top_speed = speed

func describe() -> String:
	return super() + ", top speed %d" % top_speed

У RaceCar есть всё, что есть у Car и Vehicle. Каждый вызов super() поднимается на один уровень выше, поэтому один вызов выполняет все три версии describe():

print(RaceCar.new(300).describe())
Car with 4 wheels, top speed 300

Когда ты вызываешь метод или читаешь переменную, Godot сначала ищет в собственном классе объекта, затем в его родительском классе, потом в родительском классе родителя и использует первое найденное. RaceCar.new(300).wheels находится в Vehicle, на два уровня выше.

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

class_name FlyingCar
extends Car, Plane
Parse Error: Expected end of statement after superclass, found "," instead.

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

challenge icon

Задание

Легко

В character.gd находится готовый класс Character: имя, hp, describe(), возвращающий NAME (HP HP), и attack(), возвращающий 1. Постройте на его основе ещё два уровня:

  • Warrior наследуется от Character и добавляет strength. Его конструктор передаёт имя и hp в super(). describe() добавляет , strength S к тексту родительского класса, а attack() возвращает значение strength.
  • Knight наследуется от Warrior и добавляет armor. Его конструктор передаёт имя, hp и strength в super(). describe() добавляет , armor A к тексту Warrior, а attack() возвращает значение атаки Warrior плюс 5.

Предоставленный код считывает количество следующих персонажей, а затем по одной строке на каждого персонажа: character NAME HP, warrior NAME HP STRENGTH или knight NAME HP STRENGTH ARMOR. Он выводит результат describe() и значение атаки. Для knight Arthur 120 15 8 он выводит:

Arthur (120 HP), strength 15, armor 8
Attack: 20

Ваш код должен находиться в warrior.gd и knight.gd. В main.gd находится предоставленный код ввода/вывода, и его нельзя редактировать.

Попробуйте сами

extends Node

func _ready():
	# Предоставленный код ввода/вывода: оставьте его без изменений
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var p := OS.read_string_from_stdin().split(" ")
		var c: Character
		if p[0] == "knight":
			c = Knight.new(p[1], int(p[2]), int(p[3]), int(p[4]))
		elif p[0] == "warrior":
			c = Warrior.new(p[1], int(p[2]), int(p[3]))
		else:
			c = Character.new(p[1], int(p[2]))
		print(c.describe())
		print("Attack: %d" % c.attack())
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор GDScript