JS++ | Abstract Classes and Methods
Last Updated :
04 Sep, 2018
We have explored virtual methods and 'overwrite' (early binding) and 'override' (late binding) which allow us to define base implementations for a method and more specific implementations of the method in subclasses. However, what do we do if there is no relevant base implementation that makes sense? Consider a 'talk' method. While a 'Dog' will "woof" and a 'Cat' will "meow, " what will the 'Animal' base class do? Abstract classes and methods allow us to solve this problem.
When a class is declared with the 'abstract' modifier, it cannot be instantiated. Furthermore, it allows the class to have "abstract methods." Abstract methods are methods that don't define an implementation, and the implementation is left to the derived classes. The derived classes must implement all abstract methods when inheriting from an abstract class; otherwise, we'll get a compile error.
Let's start by making our 'Animal' class in Animal.jspp abstract and declaring an abstract 'talk' method:
external $;
module Animals
{
abstract class Animal
{
protected var $element;
private static unsigned int count = 0;
protected Animal(string iconClassName) {
string elementHTML = makeElementHTML(iconClassName);
$element = $(elementHTML);
Animal.count++;
}
public static unsigned int getCount() {
return Animal.count;
}
public virtual void render() {
$("#content").append($element);
}
public abstract void talk();
private string makeElementHTML(string iconClassName) {
string result = '<div class="animal">';
result += '<i class="icofont ' + iconClassName + '"></i>';
result += "</div>";
return result;
}
}
}
If we try to compile right now, we'll get compiler errors demanding that the subclasses of 'Animal' implement the 'talk' abstract method.
Let's start with Cat.jspp:
import Externals.DOM;
external $;
module Animals
{
class Cat : Animal
{
string _name;
Cat(string name) {
super("icofont-animal-cat");
_name = name;
}
final void render() {
$element.attr("title", _name);
super.render();
}
final void talk() {
alert("Meow!");
}
}
}
We import 'Externals.DOM' because this module provides all the 'external' declarations for the DOM (Document Object Model) API for browsers. This allows us to use the 'alert' function which will pop up a message box with what we want the cat to say ("Meow!"). We could have also just declared 'alert' as 'external'. Notice that we used the 'final' modifier to override 'talk', but we could have just as well used 'override'.
We're going to implement Dog.jspp similarly, but dogs make a different sound:
import Externals.DOM;
external $;
module Animals
{
class Dog : Animal
{
string _name;
Dog(string name) {
super("icofont-animal-dog");
_name = name;
}
final void render() {
$element.attr("title", _name);
super.render();
}
final void talk() {
alert("Woof!");
}
}
}
Now let's implement Panda.jspp. Pandas can bark, so let's make it bark:
import Externals.DOM;
external $;
module Animals
{
class Panda : Animal
{
Panda() {
super("icofont-animal-panda");
}
final void talk() {
alert("Bark!");
}
}
}
One last class to implement: 'Rhino'. Let's assume rhinos don't make a sound. It's perfectly fine to just override the abstract method and have it do nothing:
external $;
module Animals
{
class Rhino : Animal
{
Rhino() {
super("icofont-animal-rhino");
}
final void talk() {
}
}
}
Notice that we didn't import 'Externals.DOM' either. We didn't need it. Our rhino doesn't talk so we don't need the 'alert' function for showing a message box.
At this point, your project should be able to compile without errors. However, our animals don't actually talk yet. We need some kind of event to trigger the animal talking. For example, we might want an animal to talk when we click on it. To achieve this, we need event handlers, and this is the subject of the next section.
Similar Reads
JS++ | Classes, OOP, and User-defined Types Up until now, we've been declaring variables, looping over data, and writing 'if' and other conditional statements. These operations comprise the "imperative programming" paradigm where we describe "how" a program operates step by step (or, more specifically, statement by statement). Oftentimes, in
6 min read
AbstractMap in Java The AbstractMap class is a part of the Java Collection Framework. It directly implements the Map interface to provide a structure to it, by doing so it makes the further implementations easier. As the name suggests AbstractMap is an abstract class by definition, therefore it cannot be used to create
10 min read
JS++ | Access Modifiers and 'super' Access modifiers allow us to change the "visibility" and "access privileges" of a class (or module) member. These are best understood by example. JS++ has three access modifiers: private, protected, and public. A private member is the least permissive. If a member is declared as 'private' it can onl
15 min read
Difference Between Data Hiding and Abstraction in Java Abstraction Is hiding the internal implementation and just highlight the set of services. It is achieved by using the abstract class and interfaces and further implementing the same. Only necessarily characteristics of an object that differentiates it from all other objects. Only the important detai
6 min read
JS++ | Interfaces As we learned in the chapter on subtype polymorphism, an operation defined for a supertype can be safely substituted with its subtypes. As a result, operations defined for 'Animal' objects can safely accept 'Cat' or 'Dog' objects. Furthermore, we mentioned that you should not confuse subtyping with
7 min read