In our cat example, we’ve been able to instantiate our cat and provide a name separately. However, it may be desirable to require the cat to be named at instantiation so that we don’t accidentally forget to name a cat. Constructors allow us to control instantiation.
By default, JS++ provides a constructor for you. This is known as the “default constructor.” It is implicitly defined by JS++ if you do not have any constructors that you’ve explicitly defined. The default constructor takes no arguments and only returns a new instance of the class. To understand the default constructor, we can explicitly define it:
external $;
module Animals
{
class Cat
{
string _name;
var $element = $(
"""
<div class="animal">
<i class="icofont icofont-animal-cat"></i>
</div>
"""
);
Cat() {
}
property string name() {
return _name;
}
property void name(string name) {
_name = name;
}
void render() {
$element.attr("title", _name);
$("#content").append($element);
}
}
}
If you try to compile the project, there should be no problems. The reason is because we are instantiating the ‘Cat’ class without arguments in our main.jspp file. If you try to provide a few arguments, you will get a compile error for incorrect code.
As you can see from our explicitly-defined default constructor, the constructor has no parameters. Additionally, it doesn’t do anything. (Constructors with no actions will still return a new instance of the class. Explicit ‘return’ statements inside constructors are unnecessary and not allowed because constructors always return a new instance of the class.)
One particular use for constructors is to initialize fields to custom values. Right now, if you instantiate the ‘Cat’ class, you will get the ‘_name’ field as an empty string. If we want instances of ‘Cat’ to always have a name, we must require it during instantiation by specifying a constructor.
First, remove the getter and setter methods. Second, change the explicit constructor we defined to take one parameter: a ‘string’ for the cat’s name. Finally, initialize the field to the argument provided to the constructor. (You should know how to do this by now.)
Your code in Cat.jspp should now look like this:
external $;
module Animals
{
class Cat
{
string _name;
var $element = $(
"""
<div class="animal">
<i class="icofont icofont-animal-cat"></i>
</div>
"""
);
Cat(string name) {
_name = name;
}
void render() {
$element.attr("title", _name);
$("#content").append($element);
}
}
}
Next, we have to change main.jspp:
import Animals;
Cat cat1 = new Cat("Kitty");
cat1.render();
Cat cat2 = new Cat("Kat");
cat2.render();
Compile the project. Open index.html in your web browser. You should see the two cats again. Hover over their images. You should once again see their names.
It’s important to note that the implicitly-defined default constructor (that takes zero arguments) is no longer defined. Once you explicitly define a constructor for a class, the default constructor will not be explicitly defined. Thus, the only way to instantiate our ‘Cat’ class now is to use the constructor that requires a name. If you try to change the code in main.jspp to instantiate a class with zero arguments, you will get a compile error.
Similar Reads
JS++ | Functions
A function is a section of code which contains a set of instructions, where the instructions describe how a particular task is to be accomplished. Functions are declared and may then be called one or more times. Declaring a function involves specifying the instructions that the function will contain
10 min read
JS++ Getters and Setters
In our previous example, we defined a 'setName' method that sets a class 'name' field we declared. A method whose sole responsibility is to write to or modify a class field is known as a "setter" or "setter method." Conversely, a method whose sole responsibility is to return the current data of a cl
4 min read
JS++ | Inheritance
So far, the only type of animal we've defined is a cat (via the 'Cat' class). Our 'Cat' class also requires us to name our cats. Finally, our 'Cat' class performs rendering to the web page. However, what if we wanted to introduce other animals? How should we implement dogs, pandas, and rhinos? While
3 min read
JS++ | Types in JavaScript
In this chapter, we're going to explore JavaScript programming styles and how developers worked with types in JavaScript (rather than JS++). This chapter will help you understand the next chapters which explain the JS++ type system in detail. In this tutorial, we will be using the Google Chrome web
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
JS++ | Upcasting and Downcasting
Now that we understand both subtyping and static versus dynamic polymorphism, we can learn about upcasting and downcasting. Upcasting and downcasting is based on type relationships. In other words, if you have data of type 'Animal', you can "downcast" it to its subtype 'Dog'. Conversely, if you have
3 min read
JS++ | Subtype Polymorphism
Subtyping describes type relationships, and subtype polymorphism enables operations defined for supertypes to be safely substituted with subtypes. Concretely, imagine the relation between a 'Cat' class and an 'Animal' class. (Remember: classes create data types in JS++.) In this case, within the con
3 min read
JS++ | Virtual Methods
As we mentioned in the previous section, if we want runtime polymorphism, using casts can lead to unclean code. By way of example, let's change our main.jspp code so that all our animals are inside an array. From there, we will loop over the array to render the animal. Open main.jspp and change the
3 min read
JS++ | Static Members and "Application-Global" Data
Up until now, all of the fields and methods that we've declared have belonged to class instances. Static members can also be added to a class. A static member is initialized at program start and is available to all instances of a class. As an example, we might want to keep a count of the number of '
4 min read
JS++ | Static vs. Dynamic Polymorphism
Static polymorphism is polymorphism that occurs at compile time, and dynamic polymorphism is polymorphism that occurs at runtime (during application execution). An aspect of static polymorphism is early binding. In early binding, the specific method to call is resolved at compile time. (JS++ also su
4 min read