Menu
CoddyTech

Interface Design

Part of the Object Oriented Programming section of Coddy's GDScript journey. Lesson 24 of 65.

An interface is a list of methods that a class promises to have, with no code behind them. Java and C# have an interface keyword; GDScript does not. You build the same thing from an abstract class whose methods are all abstract:

# drawable.gd
@abstract
class_name Drawable
extends RefCounted

@abstract func draw() -> String
@abstract func resize(factor: int) -> void

It has no variables and no method bodies. It describes what a drawable thing can do, and each class decides how:

# banner.gd
class_name Banner
extends Drawable

var text: String
var size := 1

func _init(t: String) -> void:
	text = t

func draw() -> String:
	return "Banner '%s' at size %d" % [text, size]

func resize(factor: int) -> void:
	size *= factor

A Circle can extend Drawable too, with a radius and its own draw() and resize(). Code that uses the interface depends only on it, so it works with every class that extends Drawable, including ones written later:

func render_all(items: Array[Drawable]) -> void:
	for item in items:
		item.resize(2)
		print(item.draw())
var items: Array[Drawable] = [Banner.new("Sale"), Circle.new(3)]
render_all(items)
Banner 'Sale' at size 2
Circle with radius 6

A class has one parent, so it can extend only one interface. When a class plays a second role, such as being saved to a file, extend the main interface and check the second role with has_method():

if item.has_method("save"):
	item.save()

Keep each interface small: a few methods that belong to one role. A class that extends it then writes only methods it needs.

challenge icon

Challenge

Easy

Build a media player around an interface.

  • In playable.gd, make Playable an interface: an abstract class with the abstract methods play() -> String and duration() -> int (in seconds).
  • Song extends Playable. play() returns Playing song: TITLE by ARTIST, and duration() returns its seconds.
  • Video extends Playable. play() returns Playing video: TITLE in RESOLUTIONp (for example in 1080p), and duration() returns its seconds.
  • Playlist knows only Playable. play_all() prints play() of every item, and total_time() returns the summed duration as M:SS (seconds with two digits, for example 4:05).

The constructors of Song and Video are written. The supplied code reads how many items follow, then one line per item: song TITLE ARTIST SECONDS or video TITLE RESOLUTION SECONDS. It calls play_all() and prints the total time. For song Imagine Lennon 183 and video Trailer 1080 95 it prints:

Playing song: Imagine by Lennon
Playing video: Trailer in 1080p
Total time: 4:38

Your code goes in playable.gd, song.gd, video.gd and playlist.gd. main.gd holds the supplied input/output code and cannot be edited.

Try it yourself

extends Node

func _ready():
	# Supplied input/output code: keep it as it is
	var count := int(OS.read_string_from_stdin())
	var playlist := Playlist.new()
	for i in count:
		var p := OS.read_string_from_stdin().split(" ")
		if p[0] == "song":
			playlist.add(Song.new(p[1], p[2], int(p[3])))
		else:
			playlist.add(Video.new(p[1], int(p[2]), int(p[3])))
	playlist.play_all()
	print("Total time: " + playlist.total_time())
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming

Practice on your own: Online GDScript compiler