Ruby object model at the Ruby drink-up of Sophia, January 2013


Published on

Presented at the Ruby Drink-up of Sophia Antipolis on the 8th of January 2013 by Nicolas Bondoux (@nicolas_bondoux).

Published in: Technology
  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Ruby object model at the Ruby drink-up of Sophia, January 2013

  1. 1. An introduction to Rubys object model Riviera.rb – 08/01/2013 Nicolas Bondoux
  2. 2. Overview● Introduction to module and classes● Singleton class; case of meta-classes● Tools for meta-programming● Using modules for extending objects: mixins
  3. 3. A simple classclass LinkedElement  #constructor ● A class definition  def initialize(content,link) contains    @content = content    @link = link  end – Instance methods  # setter – Constants  def content=(content)    @content = content  end – Class variables  #getter ● Instance variables are  def content    return @content prefixed by @; they  end are manipulated  # automatic generation setter/getter: through instance  attr_accessor :linkend   methods
  4. 4. Class instancesirb(main):192:0> a ="a", nil)=> #<LinkedElement:0x00000001b63b58 @content="a", @link=nil>irb(main):193:0> b ="b",a)=> #<LinkedElement:0x00000001b5daf0 @content="b", @link=#<LinkedElement:0x00000001b63b58 @content="a", @link=nil>>irb(main):194:0>> #<LinkedElement:0x00000001b63b58 @content="a", @link=nil>irb(main):195:0> b.@linkSyntaxError: (irb):195: syntax error, unexpected tIVAR from /usr/bin/irb:12:in `<main>irb(main):196:0> b.content=> "b"b.instance_variables=> [:@content, :@link]● A class be instantiated using #new (class method)● Instance variables live within the instance, but are not directly accessible → need of getter and setters
  5. 5. Objects equality● Objects comparison: – == → true if the content of two objects – .eql? → true if == and class of the two objects; ● Used alongside with .hash for hash maps – .equal? : true if the same instance on both sides● == and .eql? Must be provided by class implementation
  6. 6. Classes inheritanceclass Toto irb(main):027:0*  def myNameIs => "My Name Is Toto."    return "My Name Is #{name}." irb(main):028:0>  end => "My Name Is Titi."  def name    "Toto" irb(main):030:0* t =  end => #<Titi:0x00000001d376c8>end irb(main):035:0> t.class => Titiclass Titi < Toto irb(main):036:0>   def name t.class.superclass    "Titi" => Toto  end irb(main):037:0> t.is_a? Titiend => true irb(main):038:0> t.is_a? Toto => true irb(main):039:0> Toto === t => true irb(main):040:0> Toto.superclass => Object
  7. 7. Self● “self” keyword represents the instance in which the code is executed – inside a method definition , the instance on which method is defined – Inside class/module definition: the class/module being defined class TestSelf   puts self   def f     return self   end end # display TestSelf t = t.f.equal? t => true
  8. 8. Class methods and variablesclass TestClassMethod  #class variable  @@a=0  #class method  def self.counter    @@a=0  end  #instance method  def putsSelf    puts self    @@a+=1  endend● Class are objects: class methods are their instance methods!● Class variables are prefixed with @@● Ruby magic: class variables from parent classes are accessible to child classes● Class variables are accessible anywhere in class definition
  9. 9. Classes methods: exampleclass LinkedElement  class LinkedElementEnd  end  #class variable  @@end =  #example of constant  End = @@end  #class method  def self.end    @@end  endendirb(main):015:0* LinkedElement.end().equal? LinkedElement::End=> trueirb(main):016:0> LinkedElement.class_variables=> [:@@end]irb(main):069:0>  a="a", LinkedElement.end)=> #<LinkedElement:0x00000001931df8 @content="a", @link=#<LinkedElement::LinkedElementEnd:0x0000000152e8c8>>irb(main):070:0>"b",a)=> #<LinkedElement:0x0000000192a8c8 @content="b", @link=#<LinkedElement:0x00000001931df8 @content="a", @link=#<LinkedElement::LinkedElementEnd:0x0000000152e8c8>>>
  10. 10. Adding methods to a class● Class definition can be extended anytime● Lets add a size method to our linked list: class LinkedElement   def size     @link.size + 1   end   class LinkedElementEnd     def size      0     end   end end irb(main):081:0> a.size => 1 irb(main):082:0> b.size => 2
  11. 11. Structs● allow to dynamically create Classes, with getter and setters irb(main):008:0> MyClass =,:b, :c) => MyClass irb(main):009:0> m =,10) => m =,10) irb(main):011:0> m.a=2 => 2 irb(main):013:0> m.to_a => [2, 10, nil]● Instance of struct have, among others .eql?, .equal?, .hash methods defined !● Very useful to quickly define records, keys …● Structs can then be inherited from/extended like any classes
  12. 12. Modules● Module is a parent type of Class; – A module is an instance of Module● Modules are like classes, except that – They cannot be instantiated – No inheritance: they cannot have parent or child● Still, they are objects: – They have instance variables, (class) methods● And they also have – class variables – and instance methods → used for the mixins● Modules are useful for namespaces
  13. 13. Modules (2)module M1  #constant:  C=1  def self.f    "f1; self is #{self}"  endendmodule M2  def self.f    "f2; self is #{self}"  endendirb(main):026:0* M1.f=> "f1; self is M1"irb(main):028:0* M2.f=> "f2; self is M2"irb(main):033:0> M1::C=> 1
  14. 14. A very simplified diagram Object MyParentClass Module MyModuleInstance MyClass Class .class .superclass
  15. 15. Extending instances:● We have already seen that class methods of a class A are instance methods specific to the object A – It is possible to add methods to instances! a="5" def a.mult(x)    "#{self.to_i*x}" znd irb(main):096:0* a.mult(10) => "50"● Where is stored “mult” Method ? In the Singleton class ! irb(main):103:0> a.singleton_class => #<Class:#<String:0x000000018ec7a8>> irb(main):104:0> a.singleton_class.ancestors => [String, Comparable, Object, Kernel, BasicObject] irb(main):105:0> a.singleton_class.superclass => String
  16. 16. What are singleton classes ?● One instance has its own singleton● Those are anonymous and invisible classes, inserted at the bottom of the class hierarchy● They are used to hold methods that are specific to an instance Object class String a (a) singleton_class
  17. 17. Singleton classes of classes: meta- classes● Meta-classes: the singleton classes of methods – This is where class methods are stored!● Meta-classes magic: – when looking for a class methods ruby search in the meta-classes of all the inheritance chain! – This is because meta-classes inheritance scheme is parallel to class inheritance scheme
  18. 18. Meta-classes: a diagram Object Class MyParentClass (MyParentClass) MyClass (MyClass)Instance (Instance) .singleton_class .superclass
  19. 19. Extending the singleton classesclass Toto  #instance method of Toto # Singleton class can also be   def f accessed explicitly  end class << Toto   def h  #class method of Toto     return self  def self.g   end  end endend#class method of Toto class Totodef Toto.g   class << selfend     def i1     end# ­> def x.g  .... ­> add an instance method to      the singleton class of x !     def i2     end   end end # i1 and i2 are class methods of  Toto !!!
  20. 20. instance_eval/instance_exec● instance_eval allow to execute code in the context of an instance; – Ruby magic: self represents the instance, but methods are added to the singleton class! class TestInstanceEval   def initialize     @a=5   end end b=5 irb(main):189:0> t.instance_eval "@a" => 5 irb(main):190:0* t.instance_eval "def f; puts @a+#{b};end" => nil irb(main):191:0> t.f 10
  21. 21. Mixins● Mixins are a way to add properties to an object● They are modules referenced by classes● Instance methods of the module becomes available to instances of the class● Include: the module becomes an included module of the Class – the instance methods of an module become instance methods of the Class → used to extend classes● Extend: the module becomes an included module of the singleton of the class → allow to extends objects, add class methods to classes ...
  22. 22. Mixins: examplesmodule AppendModule  def append(x)    return,self)  endend#add append method to LinkedElement and LinkedElementEndclass LinkedElement  #add append as instance method of LinkedElement  include AppendModule  class LinkedElementEnd    include AppendModule  endendirb(main):268:0> l = LinkedElement::End.append("z").append("y").append("x")=> #<LinkedElement:0x00000001d18138 @content="x", @link=#<LinkedElement:0x00000001d18188 @content="y", @link=#<LinkedElement:0x00000001d181d8 @content="z", @link=#<LinkedElement::LinkedElementEnd:0x00000001f04f78>>>>irb(main):269:0> l.size=> 3irb(main):270:0> LinkedElement.included_modules=> [AppendModule, Kernel]
  23. 23. Any questions?