Showing posts with label OOP. Show all posts
Showing posts with label OOP. Show all posts

Saturday, February 23, 2019

5.7 Closures

The bind function takes advantage of something in JavaScript known as a closure. This takes advantage of the way that scope works within JavaScript and can be used to hide variables within a function. For binding it is making sure that the reference to the object that created the object is tracked.

Scope simply is a term that describes which variables are known to a particular piece of code. The visibility of a variable depends on where it is declared. When declared outside of a function it is global and is visible to everything, including other scripts running on the same web page, which is why you do not want to have global variables in your code if you can help it. Variables declared within a function are only visible to code within that function. Variables declared within a loop are only visible to code within that loop, and so on. The code within the loop, however, can see all the variables in the scopes leading up to it.

The purpose of scope is two-fold. First, each layer of scope can be considered it's own name-space. Second, and more importantly, this allows JavaScript to know which variables are no longer needed and can be garbage collected so that the memory it used can be reclaimed for use by other things. There is an exception to this garbage collection rule, any variable that is still being referenced by another variable that is still in scope will not be garbage collected.

Functions within another function have access to the parent function's variables. This information is stored in a scope chain, the details of which are a bit beyond the scope of this chapter but the nutshell is that the function has access to the information contained within the function that created. This means that if we have a case where there is a reference to the inside function then even if the outside function goes out of scope, the outside functions data will not be garbage collected as it is still referenced by something that is still in-scope.

Here is a simple demonstration:

// General function for printing to the web page so results can be seen// without requiring the console
function printTestLine(s) {
// we are grabbing an html element
var results = document.getElementById("testResults");
// now append the new line to this element
results.innerHTML = results.innerHTML + "
" + s

}

function HiddingVariables(p, v) {
this.publicValue = p;
var hiddenValue = v;

this.getHiddenValue = function() {
return hiddenValue;
}

this.bindPrint = function() {
var owner = this;
return function() {
printTestLine("The hidden value is " + owner.getHiddenValue());
}
}
}

var hiddenVar = new HiddingVariables(21, 42);
printTestLine("Attempting to read public variable: " + hiddenVar.publicValue);
printTestLine("Attempting to read hidden variable: " + hiddenVar.hiddenValue);
printTestLine("Getting through method: " + hiddenVar.getHiddenValue());
setTimeout(hiddenVar.bindPrint(), 1000);

When the HiddingVariables function runs, the public value is stored as part of the object. The hidden variable is a local variable which means that it will go out of scope as soon as the function finishes running. As the function has a reference to this value, it is still visible to it. If you still don't quite understand how a closure works, don't worry too much as it is not necessary to understand them to use them.

Now that we have a basic understanding of classes we use some of these concepts in the next chapter when we create the Nightmare Maze game.

Saturday, January 12, 2019

5.4 Inheritance

One of the most powerful and most over-abused features of object oriented programming is the use of inheritance. The basic idea here is that there are a lot of classes of objects that have a lot of features in common. Instead of re-writing the same code repeatedly for similar objects, a hierarchy of related classes can be created. You start with a base class, also known as the parent, that has the base functionality it's children will inherit. To demonstrate this, lets create a base class for pets.

The pet class will have a name for the pet and a species for the pet. Pets will be able to greet their owner, and make a noise. First, lets take a look at the more modern ECMAScript 6 way of doing this. This is set up just like any normal class that we would have created in the previous section.


class E6Pet {
constructor(name, species) {
this.name = name;
this.species = species
}

greet() {
printTestLine(this.name + ", the " + this.species + ", comes to greet you");
}

makeNoise() {
printTestLine(this.name + " makes a noise");
}
}

var fish = new E6Pet("Nemo", "Fish")
fish.greet();
fish.makeNoise();


The old way of creating the base class is also the same way you would create a class using older versions of ECMAScript.

function Pet(name, species) {
this.name = name;
this.species = species;

this.greet = function() {
printTestLine(this.name + ", the " + this.species + ", comes to greet you");
}

this.makeNoise = function() {
printTestLine(this.name + " makes a noise");
}

}

var oldfish = new Pet("Dora", "Fish")
oldfish.greet();
oldfish.makeNoise();

Once you have a class that can be used as a base-class, you can create a new class that inherits the methods and variables of it's parent. This effectively gives you all the code that you have written in the base class. You can then add additional methods and variables allowing the new class to have the functionality of the base class while adding new features to the class. This alone would make inheritance worth doing, but it gets even more powerful. It is possible to override an existing method and replace it with another method that is more appropriate for the class you are creating.

In our example, different pets make different sounds so by overriding  the makeNoise method, we can create species specific noises. We will create a dog and a cat, with each of them having a unique noise and the dog being able to wag it's tail.

ECMAScript 6 makes inheritance very easy as you just use the extends keyword when you are creating a class. Sub-classes can have a different number of parameters, with the super method used to call the original code. Overriding the method is simply the matter of using a method with the same "signature." A method's signature is simply the method name and the particular parameters that make up the method. finally creating a new method is done by having a new method in the class.

class E6Cat extends E6Pet{
constructor(name) {
super(name, "Cat")
}

makeNoise() {
printTestLine(this.name + " Meows!");
}
}

class E6Dog extends E6Pet {
constructor(name) {
super(name, "Dog")
}

makeNoise() {
printTestLine(this.name + " Barks!");
}

wag() {
printTestLine(this.name + " wags his tail!");
}
}

var cat = new E6Cat("Lexi")
var dog = new E6Dog("Scruffy")

cat.greet();
cat.makeNoise();
dog.greet();
dog.makeNoise();
dog.wag();

The old way of inheritance is a bit more confusing as older versions of ECMAScript does not have a way of directly indicating inheritance so the programmer must manually set this up. JavaScript use prototype based inheritance where every class has a prototype that determines which methods it has. This prototype is used by the new operator to set up the class, but the prototype can be modified manually. The result is that there are many ways of setting up inheritance in JavaScript. The most common way is simply assigning the prototype of the class to the prototype of it's parent by using the new function.

function Cat(name) {
this.name = name;
this.species = "Cat";

this.makeNoise = function() {
printTestLine(this.name + " Meows!");
}
}
Cat.prototype = new Pet();

(Dog = function(name) {
this.name = name;
this.species = "Dog";

this.makeNoise = function() {
printTestLine(this.name + " Barks!");
}

this.wag = function() {
printTestLine(this.name + " wags his tail!");
}

} ).prototype = new Pet();

var oldcat = new Cat("Abby")
var olddog = new Dog("Smokie")

oldcat.greet();
oldcat.makeNoise();
olddog.greet();
olddog.makeNoise();
olddog.wag();

You will notice two slightly different styles for doing this. The cat way is the textbook way while the dog way is the way JavaScript code generated by Animate CC does things. You could also manually copy just the methods you are interested in, which can be a handy way of inheriting functionality from multiple different classes.

Inheritance is not just for reducing code duplication, but allows for a powerful technique known as polymorphism which we will be covering next.

Saturday, December 29, 2018

5.3 Constructing Classes

While I have my January game ready, I am at my parent's place while the game is in a different city so I will not be posting it until January 2nd when I return to University.

JavaScript did not have "proper" classes until ECMAScript 6. The problem is that while there is now a class keyword that makes creating classes much easier in browsers that have an ECMAScript 6 complaint version of JavaScript, this is not all browsers. Eventually there will be so few browsers that do not support ECMAScript 6 that using JavaScript classes will make sense, but before that transition takes place, the old way of creating JavaScript classes must be used. The nice thing is that backwards compatibility means that the old way will still work on new browsers.

The ECMAScript 6 way of creating classes is with a class construct. Within this construct we have a constructor which initializes the class and then methods that the class knows. There is some special support for getter and setter methods which I will not be covering here as this book is more focused on older JavaScript but that may be something I cover in a future book. Here is what a soldier class would look like in ECMAScript 6 versions of JavaScript:

// General function for printing to the web page so results can be seen
// without requiring the console
function printTestLine(s) {
// we are grabbing an html element
var results = document.getElementById("testResults");
// now append the new line to this element
results.innerHTML = results.innerHTML + "
" + s

}

class E6Soldier {
constructor(name, rank, serialNumber) {
this.name = name;
this.rank = rank;
this.serialNumber = serialNumber; 
}

printNRS() {
printTestLine("Name: " + this.name + " Rank: " + this.rank +
" Serial Number:" + this.serialNumber);
}
}

printTestLine("ECMAScript 6 tests");
var soldier1 = new E6Soldier("Bob", "Private", 12345);
var soldier2 = new E6Soldier("Doug", "Captain", 23456);
soldier1.printNRS();
soldier2.printNRS();

You will notice that both soldiers simply used the E6Soldier class to build their object. The creation of an object from a class is called instantiation in object oriented terminology. Every object of a particular class is known as an instant of that class. Instances share the same properties and methods, though object specific properties and methods can be manually added to specific objects if desired, but are otherwise independent.

The old way of creating classes is similar to the new way but instead of grouping things into a class structure you are creating a function. This function sets up the properties just like the constructor above did and then sets up all the methods that are used by the class.

function Soldier(name, rank, serialNumber) {
this.name = name;
this.rank = rank;
this.serialNumber = serialNumber;

this.printNRS = function() {
printTestLine("Name: " + this.name + " Rank: " + this.rank +
" Serial Number:" + this.serialNumber);
}
}

Note that it is not necessary to have all the methods defined within the function. Some people actually like defining the methods of a class outside of the class. This is done by using the function's prototype, which is something we will be talking about in more detail in later sections.

Soldier.prototype.changeRank = function(newRank) {
this.rank = newRank;
}

Using the classes is pretty much the same the old way as it is the new way.

var soldier3 = new Soldier("Pete", "Private", 34567);
var soldier4 = new Soldier("Billy", "Captain", 45678);
soldier3.printNRS();
soldier4.printNRS();
soldier4.changeRank("General");
soldier4.printNRS();

The real power of classes comes from polymorphism and inheritance, but that is also where the biggest problems of object oriented programming come from. Next section we will start our exploration of polymorphism and inheritance.

Saturday, November 17, 2018

Chapter 5 Overview

Object Oriented programming has become the predominant way of developing software today. While there are some people who believe that object-oriented programming (OOP) is a misstep, there are also people who quite dogmatic about OOP. Both of the Universities I have attended tend to favor the OOP approach but there is starting to be a look at the alternatives to OOP, with functional programming gaining traction. I am a bit more flexible when it comes to programming believing that methodologies, like languages, are tools and one should try and use the appropriate tool for the problem they are dealing with.

Object Oriented approaches are so common, however, that no matter what your stance on OOP is, you should at least be familiar with the concepts behind it. This section of the book takes a look at the core OOP features that JavaScript supports. Unfortunately, like a lot of things about JavaScript, things are not as straightforward as they should be. While JavaScript has always had support for Objects, the language itself did not explicitly support OOP constructs until the ECMAScript 6 standard was released. This means that older browsers do not support the new language keywords but there are a shrinking number of people who use those browsers. It also means that there is a lot of legacy code out there that does OOP the hard way. These techniques are still valid so it is wise to at least be familiar with them.

In this chapter we will look at a number of OOP related concepts looking at what the idea behind the concept is, how ECMAScript 6 supports that concept, and the "old" way of handling the concept.

To start with, in the "NameSpace" section we will be looking at the name space problem and how to get around it. Even if you are not into the other OOP concepts, name spaces are something that ALL non-trivial programs should use.

It goes without saying that objects are important to object-oriented programming so we will then revisit creating objects in "Creating Objects". This will be followed by "Constructing Classes". Classes are what most OOP languages use to define objects with a class keyword being something that was missing from JavaScript until the ECMAScript 6 standard was released.

One of the more powerful, albeit over-abused, features of object oriented programming is the use of inheritance. This allows you to create new classes based off of existing classes without needing to write most of the functionality and will explained in the "Inheritance" section. Polymorphism is how OOP languages take advantage of inheritance by letting you use a child class in place of a parent class. JavaScipt uses a variant of polymorphism known as Duck Typing which gives you a lot of flexibility and power but has some downsides. These issues will be covered in "Polymorphism and Duck Typing".

JavaScript handles classes a bit different from most other object oriented languages. This leads to a strange issue when trying to use an objects function as a call-back. This issue can be solved using something known as binding, which we will explain in a section strangely named "Binding".

What allows JavaScript to bind functions actually is a very powerful construct known as a closure. Closures are a bit confusing and you may not want to use them in your programs, but they are an important JavaScript technique so I will be covering them in the "Closures" section.

And that should cover all the object oriented JavaScript knowledge that you will need for the remainder of this book.