Pseudoclassical Subclassing

// Class constructor
var Class = function(arg1, arg2) {
  this.arg1 = arg1;
  this.arg2 = arg2;
};

Class.prototype.method = function () {
};
// Subclass constructor
var Subclass = function(arg1, arg2) {
  Class.call(this, arg1, arg2);
  this.arg1 = arg1;
  this.arg2 = arg2;
}

// Delegates fallback prototype to Class's prototype
Subclass.prototype = Object.create(Class.prototype);

// Reseting subclass's constructor since we just overrode it 
Subclass.prototype.constructor = Subclass; 

* Use Object.create to delegate to Class prototype allows us to make a copy of it rather than modifying Class’ prototype when we’re making changes to Subclass’ prototype.

Advertisements
Pseudoclassical Subclassing

Data Modeling & Classes

Functional:

  • constructor and methods are wrapped in one class function.
  • return instance object at the end.
var ClassName = function {
  var newInstance = {};
  newInstance.methodOne = function () {
  };

  newInstance.methodTwo = function () {
  };

  return newInstance {}; 
};

Functional-shared:

  • Methods are stored in a separate object outside constructor function.
  • Uses extend to give instance access to method object.
  • Return newInstance inside constructor.
  • Methods uses ‘this’ keyword to reference newInstance.
var ClassName = function {
  var newInstance = {};
  extend(newInstance, classMethods);
  return newInstance; 
}

var classMethods = {};

classMethods.methodOne = function () {
};

classMethods.methodTwo = function () { 
}; 

Prototypal:

  • Methods are stored in a separate object outside constructor function.
  • Uses Object.create to access methods
  • Return newInstance inside constructor.
var ClassName = function {
  var newInstance = Object.create(classMethods);
  return newInstance; 
}

var classMethods = {};

classMethods.methodOne = function () {
};

classMethods.methodTwo = function () { 
}; 

Pseudoclassical (most commonly used pattern)

  • Uses the ‘new’ keyword to instantiate a new instance.  (‘new’ replaces the need for Object.create and returning the object inside the constructor).
  • Methods stored on the prototype chain.
  • Uses ‘this’ keyword to reference the new instance.
var ClassName = function {
  this.length = 5;
}

ClassName.prototype.methodOne = function () {
};

ClassName.prototype.methodTwo = function () { 
};

var newInstance = new Class();

 

Data Modeling & Classes

Hackerrank Day 21: Generics

Task
Write a single generic function named printArray; this function must take an array of generic elements as a parameter (the exception to this is C++, which takes a vector). The locked Solution class in your editor tests your function.

Note: You must use generics to solve this challenge. Do not write overloaded functions.

Input Format

There is no input for this challenge. The locked Solution class in your editor will pass two different types of arrays to your printArray function.

Constraints

  • You must have exactly 1 function named printArray.

Output Format

Your printArray function should print each element of its generic array parameter on a new line.

My Solution in Java 8:

screen-shot-2016-12-28-at-1-11-18-pm

I still don’t really understand Generics so I’m just going to put what I got from the internet here for future references.

What is Generics?

Generic constructs are a very efficient way of reusing your code. In the same way you have parameters for a function, generics parameterize type and allow you to use apply the same interface, class, or method using different data types while still restricting operations to that data type (meaning that you still get strong type checking at compile time).

public interface List<E> extends Collection<E>
public interface Map<K,V>

The letters enclosed between angle brackets (< and >) are type parameters and, like many things in programming, there is a convention behind them (remember, following conventions help us write clean, readable code!). The letters below are commonly-used generic type parameters:

  • E – Element
  • K – Key
  • V – Value
  • N – Number
  • T – Type (e.g.: data type)
  • S,U,V, etc. These are second, third, and fourth types for when T is already in use.

A parameterized type is basically a class or interface name that is immediately followed by a type parameter in angle brackets. Observe that List and Map are both parameterized types, and their respective parameters (E, K, and V) all follow the conventions shown above. This helps us make some assumptions about the type of objects these type parameters are standing in for.

Just like we pass arguments to functions and methods, we need to specify data types for our type parameters when we instantiate generic objects.

Once a data type is specified and an object is created, the specified type replaces every ocurrence of the generic type parameter in the instantiated class. The compiler also performs strict type checking to ensure you haven’t tried to do anything not allowable for that data type (e.g.: trying to add an element to integerList that isn’t of type Integer).

Why use Generics?

Code that uses generics has many benefits over non-generic code:

  • Stronger type checks at compile time.
    A Java compiler applies strong type checking to generic code and issues errors if the code violates type safety. Fixing compile-time errors is easier than fixing runtime errors, which can be difficult to find.
  • Elimination of casts.
    The following code snippet without generics requires casting:

    List list = new ArrayList();
    list.add("hello");
    String s = (String) list.get(0);
    

    When re-written to use generics, the code does not require casting:

    List<String> list = new ArrayList<String>();
    list.add("hello");
    String s = list.get(0);   // no cast
    
  • Enabling programmers to implement generic algorithms.
    By using generics, programmers can implement generic algorithms that work on collections of different types, can be customized, and are type safe and easier to read.
Hackerrank Day 21: Generics

Hackerrank Day 19: Interfaces

Interface
Abstraction is the separation between what something does and how it’s accomplished. An interface is a collection of abstract methods and constants that form a common set of base rules/specifications for those classes that implement it. Much like an abstract class, an interface cannot be instantiated and must be implemented by a class.

By having classes implement the interface (as opposed to having them be completely separate standalone classes), we ensure that all classes (and any future classes that implement that interface) will follow the same basic rules. Knowing the rules for the interface allows us to independently write code that uses some features of the interface, regardless of how it’s implemented.

**If we add another method to the interface, we must add an implementation for that method to each class that implements the interface, in order for the code to compile.

screen-shot-2016-12-26-at-10-00-08-pm

My Solution in Java 8: 

screen-shot-2016-12-26-at-9-59-24-pm

(Ruby does not formally support interfaces like Java or C#, so this challenge was completed in Java 8.   However, interface is a relevant concept to Ruby, which can be read more about here.)

Also, as a side note:   When writing multiple classes in the same file, do not use an access modifier (e.g.: public) in your class declaration (or your code will not compile).  However, you must use the public access modifier before your method declaration for it to be accessible by the other classes in the file.

Hackerrank Day 19: Interfaces

Hackerrank Day 18: Queues and Stacks

Task:

A palindrome is a word, phrase, number, or other sequence of characters which reads the same backwards and forwards. Can you determine if a given string, s , is a palindrome?

screen-shot-2016-12-25-at-3-35-09-pm

My Solution: 

Screen Shot 2016-12-25 at 3.46.51 PM.png

screen-shot-2016-12-25-at-3-44-57-pm

Things learned in this challenge:

  • The attr_accessor method lets you create, read(attr_reader), and write (attr_writer) instance variables all in one step.   If we didn’t use it, we would have to write all of this out:

screen-shot-2016-12-25-at-3-52-37-pm

  • An array can be a stack or queue by limiting yourself to stack or queue methods (push, pop, shift, unshift). Using push / pop gives LIFO behavior (stack), while using push / shift gives FIFO behavior (queue).
  • A stack is a data structure that uses a principle called Last-In-First-Out (LIFO), meaning that the last object added to the stack must be the first object removed from it.At minimum, any stack should be able to perform the following three operations:
    • Peek: Return the object at the top of the stack (without removing it).
    • Push: Add an object passed as an argument to the top of the stack.
    • Pop: Remove the object at the top of the stack and return it.
  • A queue is a data structure that uses a principle called First-In-First-Out (FIFO), meaning that the first object added to the queue must be the first object removed from it. You can analogize this to a checkout line at a store where the line only moves forward when the person at the head of it has been helped, and each person in the line is directly behind the person whose arrival immediately preceded theirs.At minimum, any queue should be able to perform the following two operations:
    • Enqueue: Add an object to the back of the line.
    • Dequeue: Remove the object at the head of the line and return it; the element that was previously second in line is now at the head of the line.
Hackerrank Day 18: Queues and Stacks

Hackerrank Day 17: More Exceptions

screen-shot-2016-12-24-at-12-05-15-pm

A quick review on Ruby Exceptions: 

An exception is a special kind of object that indicates that something has gone wrong. When this occurs, an exception is raised (or thrown). By default, Ruby programs terminate when an exception occurs. But it is possible to declare exception handlers. An exception handler is a block of code that is executed if an exception occurs during the execution of some other block of code. Raising an exception means stopping normal execution of the program and transferring the flow-of-control to the exception handling code where you either deal with the problem that’s been encountered or exit the program completely. Which of these happens – dealing with it or aborting the program – depends on whether you have provided a rescue clause . If you haven’t provided a rescue clause, the program terminates; if you have, control flows to the rescue clause.

catch/throw are NOT the same as raise/rescue.

  • raise, failrescue, and ensure handle errors/exceptions
  • throw and catch are control flow

(Terminating a single level of control flow, like a while loop, can be done with a simple return. Terminating many levels of control flow, like a nested loop, can be done with throw.)

Unlike in other languages, Ruby’s throw and catch are not used for exceptions. Instead, they provide a way to terminate execution early when no further work is needed. (Grimm, 2011)

While the exception mechanism of raise and rescue is great for abandoning execution when things go wrong, it’s sometimes nice to be able to jump out of some deeply nested construct during normal processing. This is where catch and throw come in handy. (Thomas and Hunt, 2001)

Based on what I learned above, throw and catch should not be used in this problem because we don’t want to terminate the entire program.  We just want to raise an error for when the input does not meet criteria.

My solution: 

screen-shot-2016-12-24-at-12-08-07-pm

Also came across a pretty handy resource on Ruby gotchas and caveats.

Hackerrank Day 17: More Exceptions

Hackerrank Day 15: Linked List

Linked List: A data structure that consists of a group of nodes which represent a sequence together.

  • Order matters (can’t move nodes around)
  • Space is dynamic
  • Each node contains data and reference to the next node.
  • The last node does not have reference to the next node because  it’s the last one and there’s nothing to reference to.

A real life example would be a train (linked list) made up of multiple train cars (nodes).  Each car contains data of how many people are in the car, and it references to the next car (except the last car which references nothing/null).

screen-shot-2016-12-23-at-3-21-28-pm

My solution in Ruby:

I managed to solve this problem by digging around other people’s codes (in other languages), but I’m still not quite sure I understand it completely..

screen-shot-2016-12-23-at-3-19-07-pm

Things I learned:

  • You could implement a linked list using classes, but arrays will give linked-list like behavior using the standard array methods. Below is an example of a linked list.
# A very simple representation
class Node
  attr_accessor :value, :next_node

  def initialize(value, next_node=nil)
    @value = value
    @next = next_node
  end
end

class LinkedList

  def initialize(value)
    @head = Node.new(value)
  end

  def add(value)
    current = @head
    while !current.next_node.nil?
      current = current.next_node
    end
    current.next_node = Node.new(value)
  end
end

ll = LinkedList.new
ll.add(10)
ll.add(20)
Hackerrank Day 15: Linked List