DBC Blog

Phase 0

Week 6 11/06/2015

In the sixth week of Dev Bootcamp, we looked a bit more in depth into classes and nested data-structures. For this entry, I want to discuss classes and give an illustrative example.

The idea of a class

Classes are what we use to model real world objects. Think of how you might describe an object. You would use adjectives (nouns) to specify particular qualities of the objects - e.g. ocean water is cool, blue, and salty. However, you can also describe an object by verbs - by what it does or has done to it. Water allows energy to be transmitted in the form of waves. Water freezes. Water causes Sharknados. A class is an abstraction of an object specified by its instance variables (i.e. nouns) and class methods (i.e. verbs). We construct a class (called Splat) as follows:

      
          Class Splat {

          def initialize(var1, var2, ...)
            @var1 = var1
            @var2 = var2
              .
              .
              .
          end

          # The rest of your method defintions go here
        }
       
    

Let us note a few things: First, class names are captalized; next, classes have an initialize method. This is the method you use to create new new objects of type Splat. To create a new Splat-object (called shirleys_splat for example), you would declare

      
          shirleys_splat = Splat.new(var1, var2, ...)
      
    

Please note that the variables var1, var2, ... are optional. The variables denoted @var1, @var2, ... are called instance variables. Instance variables are 'visible' only inside of the class itself. You cannot alter instance variables from outside of a class (unless you define a class method that allows you to so). Instance variables differ from local variables in that local variables are only visible inside the method they appear in. Instance variables visible in all methods defined iin the class. On other words, once you have declared an instance variable in a class method, you are free to define other class methods that also use that instance variable. For example, suppose that Splat has the following methods

      
          def method1
            @var1 = 0
            @var2 = 'Gravy!'
            var3 = 22.5

            # Put code here to make method1 do something
          end

          def method2
            @var1 = 0
            var4 = "Bug spray"

            # Put code here to make method2 do something
          end
      
    

In the above methods @var1 is an instance variable and so can appear in methods. On the other hand, var4 is local and can only be used in method2 and not in method1. There are other concepts related to classes (such as class variables), that I won't go into. This is only intended to be a first exposure to these ideas.

An example of a class

Let's consider a super villain. At the very least, a super villain can be specified by a name (e.g. The Harmulator), type (e.g. mad scientist, superpowered psychopath), special power (e.g. heat vision, super garlic breath) and by costume color. Some actions related to super villains include:

  • taking hostages
  • belittling minions
  • blowing things up
  • making demands

With this in mind, let's construct our basic super villain class.

      
        class SuperVillain 

          def initialize(name, type, super_power, costume_color)
            @name = name
            @type = type
            @super_power = super_power
            @costume_color = costume_color
            @hostages = []
            @to_be_demolished = []
            @proclamations = ["I hearby ban Nutella!", "Bring me ... One Million Kumquats!"]
          end

          def take_hostage(hostage)
            puts "#{hostage}! You have been taken hostage"   
            return @hostages + hostage.to_a   # This allows both individual hostages and groups of hostages to be taken             
          end

          def belittle_minion()
            print "Your mother wears necropants and your father invented crab shampoo!"
          end

          def demolish(monument)
            puts "Murdiddily-urder #{monument}"
            @to_be_demolished + monument.to_a
          end

          def make_proclamation()
            print @proclamations.shuffle[0]
          end

        end
      
    

Let's construct a new super villain:

      
       puts harm = SuperVillain.new("The Harmulator", "mad scientist", "super halitosis", "Blood Red")
       puts harm.take_hostage(["Willow","Wesley",["J.Crew Models"]])
       puts harm.belittle_minion()
       puts harm.demolish(["Star Bucks", "Trump Tower"])
       puts harm.make_proclamation()

       # with resulting output
       => nil
       ["Willow", "Wesley", ["J.Crew Models"]]! You have been taken hostage
       Willow
       Wesley
       J.Crew Models
       Murdiddily-urder ["Star Bucks", "Trump Tower"]
       Star Bucks
       Trump Tower
       Bring me ... One Million Kumquats!
      
    

Notice that all of the variables are instance variables, however, that does not always need to be the case. There are some issues that I have ignored. For example, how do you print out or change the values of the instance variables? In other languages you would have to explicitly define 'get' and 'set' methods. However, in Ruby there is a shortcut called the attr_* family of methods. For example, in SuperVillain, adding the line attr_reader :name gives you a method that will return the value of name, while adding attr_reader :costume_color gives you a method that allows you to change the value of costume_color. There are many other aspects of classes that I have not talked about. I only wanted to you a brief first exposure to this topic.