Learning Outcome 15th January 2020
Introduction
I learned about Interface-based Polymorphism as I was working a task to abstract some conditionals in my TicTacToe PlayGame()
function.
What is Polymorphism?
Polymorphism is an object-oriented programming concept that refers to the ability of a variable, function or object to take on multiple forms. Read more about Polymorphism here
What is Interface?
An interface is a syntactical contract that an entity should conform to. In other words, an interface defines the syntax that any entity must adhere to. Read more about Interface here
My Tic Tac Toe game has 3 player types, A Human Player, An Unbeatable player(Minimax), and a Beatable player (Random Player). All three player are setup in their separate modules and a method(function) responsible for finding the best position on the game board for every state of the game.
In my playGame()
loop, I had some conditionals which checks the player that has the current turn, and expects a move by invoking its move inbuilt method function
You will notice that on line 41
, 43
, and 45
, irrespective of who the player is, all i needed was a move
, which in this case returns a position on the board for the current player
The best way I went about this was to adopt the Interface-based approach to Polymorphism by defining an interface Player
that has a contract getMove
which takes in board as an argument and returns a Promise of type number
.
A class or function can implement an interface to define the implementation of the properties as defined in that interface. So I created three separate Player modules for each player type and have them stick to the same contract as the interface.
The HumanPlayer
class with an async
getMove()
function that implements the Player Interface
and returns a promise number.
Note that the getMove
function here is asynchronous,
this is to enable me await
the return value since this.display.askUserForInput
is also an asynchronous
function
The UnbeatablePlayer
class with a getMove()
function that implements the Player Interface
and returns a promise number.
Because I must abide by the contract of the Player Interface,
I had to wrap the return value from this.minimax.findBestMove()
in Promise.resolve()
function
Also did the same for the BeatablePlayer
class which also defines a getMove()
function that implements the Player Interface
and returns a promise number.
Now in my PlayGame()
function loop, I just call the getMove()
function on the currentPlayer
object to return the move
of the turn taking player
Why Use Interface?
As I have learned, an interface defines the specification of entities and they can be implemented by classes or functions
You can create multiple implementations of a single interface Interface
A class can implement more than one interface at a time.
An interface can extend another interface
You can add more properties(methods or functions) in the implementing class, which is not in the interface contract being implemented, however you must also implement all the existing properties available within the implemented interface unless they are optional.
You can define optional properties on an interface using
?
and read-only properties by using thereadonly
keyword in the property name
Reference: