Tuesday, November 15, 2011

Objects in practice: class basics in Java and Ruby

This post looks at basic class and inheritance mechanisms in both Java and Ruby. I might to decide to expand this into a series, illustrating basic programming building blocks using Java, Ruby, and Scala; we'll see how it goes.

For this post, we are modeling employees of a software company, something like:
(via YUML:
edit)


NOTE:  This is NOT a good design--doesn't allow employees to fulfill multiple roles, doesn't account for changes over time--but I'll show better designs in later Howtos.

So, the general idea is that we want to reuse some behavior and also provide some specialized behavior. Probably the most simplistic way to do this in OO languages is to set up concrete inheritance and leverage polymorphism. I'll show how this is done in Java and Ruby, and the complete code can be found at github

JAVA

A simple parent class, provides startDate member and monthsOnJob to subclasses:

public class Employee {
  private Date startDate;

  public Integer monthsOnJob() {
    Integer months = 0;
    // Do the math
    return months;
  }

  public String jobDescription() {
    return "New employee"; // Default description, will be overriden by subclasses
  }
}
A simple subclass, adding behavior to the super and overriding the description

public class Developer extends Employee {

  @Override
  public String jobDescription() {
    return "Developer: " + listTechnicalSkills(); 
  }

  private String listTechnicalSkills() {
    String skillStr = "";
    // TODO get skills from getTechnicalSkills and build string
    return skillStr;
  }

  private Collection technicalSkills;

  public Collection getTechnicalSkills() {
    return technicalSkills;
  }

  public void setTechnicalSkills(Collection technicalSkills) {
    this.technicalSkills = technicalSkills;
  }
}
Another specialization, Manager has Employees as reports

public class Manager extends Employee {
  Collection reports;

  @Override
  public String jobDescription() {
    return "Suit";
  }

  public Collection<Employee> getReports() {
    return reports;
  }
}


Ruby
Now the parent class in Ruby

class Employee
  attr_accessor :start_date # method that creates accessors

  def initialize(start)
    @start_date = start
  end

  def months_on_job
    # Math is easy
    (Date.today.year*12 + Date.today.month) - (@start_date.year*12 + @start_date.month)
  end

  def job_description
    "New employee"
  end

end
A Ruby Developer class

class Developer < Employee

  attr_accessor :technical_skills

  def initialize(start)
    super(start)
    @technical_skills = []
  end

  def job_description
    ret = "Developer: "
    @technical_skills.each {|skill| ret << " ${skill"}
  end

end
The Manager

class Manager < Employee

  attr_accessor :reports # accessor
  def initialize(start)
    super(start)
    @reports = []
  end

  def job_description
    "Suit"
  end

end