ruby object model at the ruby drink-up of sophia, january 2013

23
An introduction to Ruby's object model Riviera.rb – 08/01/2013 Nicolas Bondoux

Upload: rivierarb

Post on 19-Jan-2015

258 views

Category:

Technology


1 download

DESCRIPTION

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

TRANSCRIPT

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

An introduction to Ruby's object model

Riviera.rb – 08/01/2013

Nicolas Bondoux

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

Overview● Introduction to module and classes

● Singleton class; case of meta-classes

● Tools for meta-programming

● Using modules for extending objects: mixins

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

A simple class● A class definition

contains

– Instance methods

– Constants

– Class variables● Instance variables are

prefixed by @; they are manipulated through instance methods

class LinkedElement  #constructor  def initialize(content,link)    @content = content    @link = link  end

  # setter  def content=(content)    @content = content  end

  #getter  def content    return @content  end

  # automatic generation setter/getter:  attr_accessor :linkend  

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

Class instances

● A class be instantiated using #new (class method)

● Instance variables live within the instance, but are not directly accessible → need of getter and setters

irb(main):192:0> a = LinkedElement.new("a", nil)=> #<LinkedElement:0x00000001b63b58 @content="a", @link=nil>

irb(main):193:0> b = LinkedElement.new("b",a)=> #<LinkedElement:0x00000001b5daf0 @content="b", @link=#<LinkedElement:0x00000001b63b58 @content="a", @link=nil>>

irb(main):194:0> b.link()=> #<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]

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

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

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

Classes inheritanceclass Toto  def myNameIs    return "My Name Is #{name}."  end  def name    "Toto"  endend

class Titi < Toto  def name    "Titi"  endend

irb(main):027:0* Toto.new.myNameIs=> "My Name Is Toto."irb(main):028:0> Titi.new.myNameIs=> "My Name Is Titi."

irb(main):030:0* t = Titi.new=> #<Titi:0x00000001d376c8>irb(main):035:0> t.class=> Titiirb(main):036:0> t.class.superclass=> Totoirb(main):037:0> t.is_a? Titi=> trueirb(main):038:0> t.is_a? Toto=> trueirb(main):039:0> Toto === t=> trueirb(main):040:0> Toto.superclass=> Object

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

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  endend# display TestSelf

t = TestSelf.newt.f.equal? t=> true

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

Class methods and variables

● 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

class TestClassMethod  #class variable  @@a=0  #class method  def self.counter    @@a=0  end  #instance method  def putsSelf    puts self    @@a+=1  endend

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

Classes methods: exampleclass LinkedElement  class LinkedElementEnd  end  #class variable  @@end = LinkedElementEnd.new

  #example of constant  End = @@end  #class method

  def self.end    @@end  endend

irb(main):015:0* LinkedElement.end().equal? LinkedElement::End=> trueirb(main):016:0> LinkedElement.class_variables=> [:@@end]

irb(main):069:0>  a= LinkedElement.new("a", LinkedElement.end)=> #<LinkedElement:0x00000001931df8 @content="a", @link=#<LinkedElement::LinkedElementEnd:0x0000000152e8c8>>

irb(main):070:0> b=LinkedElement.new("b",a)=> #<LinkedElement:0x0000000192a8c8 @content="b", @link=#<LinkedElement:0x00000001931df8 @content="a", @link=#<LinkedElement::LinkedElementEnd:0x0000000152e8c8>>>

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

Adding methods to a class● Class definition can be extended anytime

● Let's add a size method to our linked list:

class LinkedElement  def size    @link.size + 1  end  class LinkedElementEnd    def size     0    end  endend

irb(main):081:0> a.size=> 1irb(main):082:0> b.size=> 2

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

Structs● Struct.new allow to dynamically create Classes, with getter

and setters

● 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

irb(main):008:0> MyClass = Struct.new(:a,:b, :c)=> MyClassirb(main):009:0> m = MyClass.new(1,10)=> m = MyClass.new(1,10)

irb(main):011:0> m.a=2=> 2

irb(main):013:0> m.to_a=> [2, 10, nil]

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

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

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

Modules (2)module M1  #constant:  C=1

  def self.f    "f1; self is #{self}"  endend

module M2  def self.f    "f2; self is #{self}"  endend

irb(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

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

A very simplified diagram

Instance MyClass Class

Object

MyParentClass Module MyModule

.class .superclass

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

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!

● Where is stored “mult” Method ? In the Singleton class !

a="5"

def a.mult(x)   "#{self.to_i*x}"znd

irb(main):096:0* a.mult(10)=> "50"

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

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

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

a (a)singleton_class

Object

Stringclass

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

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

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

Meta-classes: a diagram

Instance

MyClass

Object

MyParentClass

.singleton_class .superclass

(MyClass)

(MyParentClass)

Class

(Instance)

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

Extending the singleton classesclass Toto  #instance method of Toto  def f  end

  #class method of Toto  def self.g  endend

#class method of Totodef Toto.gend

# ­> def x.g  .... ­> add an instance method to the singleton class of x !

# Singleton class can also be accessed explicitlyclass << Toto  def h    return self  endend

class Toto  class << self    def i1    end        def i2    end  endend# i1 and i2 are class methods of Toto !!!

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

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  endendb=5

irb(main):189:0> t.instance_eval "@a"=> 5irb(main):190:0* t.instance_eval "def f; puts @a+#{b};end"=> nilirb(main):191:0> t.f10

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

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 ...

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

Mixins: examplesmodule AppendModule  def append(x)    return LinkedElement.new(x,self)  endend

#add append method to LinkedElement and LinkedElementEnd

class LinkedElement  #add append as instance method of LinkedElement  include AppendModule  class LinkedElementEnd    include AppendModule  endend

irb(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=> 3

irb(main):270:0> LinkedElement.included_modules=> [AppendModule, Kernel]

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

Any questions?