Friday, May 25, 2012

How do you define classes in ruby?

To define a class in ruby, you simply have to type class MyClass. The naming convention of capitalizing class names is enforced in ruby, so you have to start class names with a capital letter. The class definition is terminated by and end statement.


The constructor of every class in ruby is called initialize. You can define a constructor by simply defining a function with that name, and any arguments you pass to MyClass.new will be passed to initialize. You do not have to specify a constructor if you don't want to; ruby will create one with no parameters that does nothing if you like. In this case, every field will initially be nil, if you try to access it.


Object fields in ruby are denoted by the enforced convention of the @ sign. For example, saying


class DListNode
  def initialize
    @item = 5
  end
end


will, on the creation of a new DListNode object, set the object's size field to 5. You can define methods just as you defined the constructor, although obviously methods can have any name you like. Except they can't start with a capital letter. Or @.


Ruby has a very cool convention for writing functions to access object fields. There are three built in functions called attribute_accessor, attribute_reader and attribute_writer, which each take in a variable number of symbols and set permissions accordingly. For example, if you wanted to have the size of a DList (doubly linked list data structure) be accessible to any program that wanted to read it, but keep programs from changing it, you would say attribute_reader :size, conventionally before you define initialize. This means that some other program would be able to say my_dlist.size and it would return the correct value, but it would not be able to say my_dlist.size = 6.


If you wanted to make the size field totally public, you could say attribute_accessor :size instead, which would allow other programs to change my_dlist.size. If for some reason (I can't think of any at the moment) you only wanted other programs to have write access, you could say attribute_writer :size.


Note that this means, if you specified attribute_reader for a field, you do not have to refer to it with the @ prefix later on. However, if you did not specify read access, you still need to say @size, instead of just size. This is because, I believe, ruby looks at the object fields first when looking for a value of a name inside a class.


Here's a full (though not fully well encapsulated) implementation of a doubly linked list in ruby for you to look over.




class DListNode
  attr_accessor :item, :nextone, :prevone
  def initialize(item=nil, nextone=nil, prevone=nil)
    @item = item
    @next = nextone
    @prevone = prevone
  end
  def to_s
    if nextone.item == nil
      return item.to_s unless item == nil
      return 'nil'
    end
    return item.to_s + ', ' + nextone.to_s unless item == nil
    return 'nil, ' + nextone.to_s
  end
end


class DList
  attr_reader :size
  def initialize
    @size = 0
    @head = DListNode.new
    @head.nextone = @head
    @head.prevone = @head
  end
  def add item
    node = DListNode.new item
    node.prevone = @head.prevone
    node.nextone = @head
    node.prevone.nextone = node
    node.nextone.prevone = node
    @size += 1
  end
  def to_s
    '['+@head.nextone.to_s+']'
  end
end


So that's how to define classes in ruby.

No comments:

Post a Comment