Menu
CoddyTech

Classes e Métodos Abstratos

Parte da seção Programação orientada a objetos do Journey de GDScript da Coddy. Lição 23 de 65.

Algumas classes existem apenas para serem estendidas. Toda forma tem uma área, mas você não pode calculá-la até saber se a forma é um círculo ou um retângulo. Marque essa classe como @abstract, na linha acima de class_name:

# shape.gd
@abstract
class_name Shape
extends RefCounted

@abstract func area() -> float
@abstract func perimeter() -> float

func describe() -> String:
	return "Area %.1f, perimeter %.1f" % [area(), perimeter()]

Uma @abstract func tem uma assinatura e nenhum corpo: nenhum dois-pontos e nenhum código depois dela. Isso significa que cada classe filha deve fornecer esse método. describe() é um método normal; as classes filhas o herdam, e ele já pode chamar os métodos abstratos.

Você não pode criar um objeto de uma classe abstrata. Shape.new() interrompe o programa antes que ele comece com Parse Error: Cannot construct abstract class "Shape".

Uma classe filha que implementa todos os métodos abstratos é uma classe normal:

# rectangle.gd
class_name Rectangle
extends Shape

var width: float
var height: float

func _init(w: float, h: float) -> void:
	width = w
	height = h

func area() -> float:
	return width * height

func perimeter() -> float:
	return 2 * (width + height)
var rect := Rectangle.new(4.0, 6.0)
print(rect.describe())
Area 24.0, perimeter 20.0

Se uma classe derivada deixar de implementar algum deles, o Godot informa isso antes de executar: Class "Square" must implement "Shape.perimeter()" and other inherited abstract methods or be marked as "@abstract". Assim, todo objeto que você pode criar tem area() e perimeter().

Uma classe abstrata ainda pode ter variáveis e um _init(). As classes filhas o chamam com super(), como de costume.

challenge icon

Desafio

Fácil

Uma loja aceita dois métodos de pagamento. Cada pagamento tem um valor e um recibo, mas a taxa e o nome dependem do método.

  • Defina PaymentMethod como abstrata e declare dois métodos abstratos: fee() -> float e method_name() -> String. Escreva receipt(), que retorna NAME: paid AMOUNT, fee FEE, total TOTAL com duas casas decimais para cada número (o total é o valor mais a taxa).
  • CreditCard: a taxa é 3% do valor (amount * 0.03), e o nome é Credit card.
  • BankTransfer: a taxa é 1.5, ou 0.0 quando o valor é 100 ou mais, e o nome é Bank transfer.

As classes filhas usam o construtor de PaymentMethod. O código fornecido lê quantos pagamentos vêm em seguida e, depois, uma linha por pagamento: card AMOUNT ou transfer AMOUNT. Ele imprime cada recibo e a soma das taxas. Para card 50 e transfer 120, ele imprime:

Credit card: paid 50.00, fee 1.50, total 51.50
Bank transfer: paid 120.00, fee 0.00, total 120.00
Total fees: 1.50

Seu código deve ficar em payment_method.gd, credit_card.gd e bank_transfer.gd. main.gd contém o código fornecido de entrada/saída e não pode ser editado.

Experimente você mesmo

extends Node

func _ready():
	# Código de entrada/saída fornecido: mantenha-o como está
	var count := int(OS.read_string_from_stdin())
	var total_fees := 0.0
	for i in count:
		var p := OS.read_string_from_stdin().split(" ")
		var payment: PaymentMethod
		if p[0] == "card":
			payment = CreditCard.new(float(p[1]))
		else:
			payment = BankTransfer.new(float(p[1]))
		print(payment.receipt())
		total_fees += payment.fee()
	print("Total fees: %.2f" % total_fees)
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação orientada a objetos

Pratique por conta própria: Compilador de GDScript online