Your SlideShare is downloading. ×
Ruby objects
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Saving this for later?

Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime - even offline.

Text the download link to your phone

Standard text messaging rates apply

Ruby objects

2,109
views

Published on

Ruby is an object-oriented programming language; that much, everyone knows. But Ruby's objects work very differently from many other languages, especially if you're coming from a complied, statically …

Ruby is an object-oriented programming language; that much, everyone knows. But Ruby's objects work very differently from many other languages, especially if you're coming from a complied, statically typed language. In this lecture, I'll review the surprisingly simple rules that govern Ruby's objects. I discuss methods, classes, instances, and modules, and how these various pieces fit together into an integrated whole -- including such topics as inheritance, instance variables, class variables, mixins, and "include" vs. "extend".

Published in: Technology

0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,109
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
107
Comments
0
Likes
6
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide























































































































  • Transcript

    • 1. Objects in Ruby Reuven M. Lerner reuven@lerner.co.il September 21st, 2010
    • 2. Warning!
    • 3. Warning! • We’ll be getting into seriously hairy object stuff today. • This is both fun and useful, but can be tricky. • Please stop me and ask questions whenever you need!
    • 4. Dynamic typing • Ruby uses dynamic typing — meaning that variables don’t have types >> a = [1,2,3] => [1, 2, 3] >> a = 'hello' => "hello" >> a = {:a => 5, :b => 6} => {:b=>6, :a=>5}
    • 5. Strict typing • But data does have types, and those types are strictly enforced: >> puts 5 + "5" TypeError: String can't be coerced into Fixnum from (irb):30:in `+' from (irb):30 from :0
    • 6. Everything is an object! • Numbers and Strings • Arrays and hashes • true, false, nil • Regular expressions, ranges • Files • Classes, Modules
    • 7. Object ID? • Every object in Ruby has an object ID, a unique integer • Builtin objects have permanent IDs • Objects that you define or create have their own object IDs • If the object IDs are equal, then we’re talking about the same object
    • 8. Object IDs >> a = [1,2,3] => [1, 2, 3] >> a.object_id => 2164172220 >> b = [1,2,3] => [1, 2, 3] >> b.object_id => 2164142300 >> a = b => [1, 2, 3] >> a.object_id - b.object_id => 0
    • 9. What is equality? • You can compare them with ==, to see if their contents are equal • You can compare their object IDs, to see if they point to the same piece of data
    • 10. That’s nice — but what is an object? • Every object is two things: • Some state (instance variables) • A pointer to a class
    • 11. OK, and what is a class? • A class is four things: • Some state (because they’re objects) • A pointer to a class (because they’re objects) • A parent class • Zero or more methods
    • 12. Whoa! • A class is an object? • Yes. • What is its class? • Class. (Which is a constant identifier.) • So a class is an instance of Class? • Yes.
    • 13. Examples >> 60.class => Fixnum >> 60.class.class => Class >> "hello".class => String >> "hello".class.class => Class
    • 14. Let’s define a class >> class MyClass >> end >> o = MyClass.new => #<MyClass:0x102ffdef0> >> o.class => MyClass
    • 15. Let’s define a class >> class MyClass Class definition >> end >> o = MyClass.new => #<MyClass:0x102ffdef0> >> o.class => MyClass
    • 16. Let’s define a class >> class MyClass Class definition >> end >> o = MyClass.new New object, class is MyClass => #<MyClass:0x102ffdef0> >> o.class => MyClass
    • 17. Let’s define a class >> class MyClass Class definition >> end >> o = MyClass.new New object, class is MyClass => #<MyClass:0x102ffdef0> >> o.class See? I told you! => MyClass
    • 18. Methods • Methods are defined on classes • When we invoke a method on object o, Ruby looks in o’s class (MyClass) for a method of that name • Ruby does this at runtime • Ruby has only one type of method! • No static, virtual, final, abstract, etc.
    • 19. Method example >> class MyClass >> def say_hello >> puts "hello" >> end >> end => nil >> o = MyClass.new => #<MyClass:0x1036160d0> >> o.say_hello hello => nil
    • 20. Method example >> class MyClass >> def say_hello >> puts "hello" Method definition >> end >> end => nil >> o = MyClass.new => #<MyClass:0x1036160d0> >> o.say_hello hello => nil
    • 21. Method example >> class MyClass >> def say_hello >> puts "hello" Method definition >> end >> end => nil >> o = MyClass.new New instance => #<MyClass:0x1036160d0> >> o.say_hello hello => nil
    • 22. Method example >> class MyClass >> def say_hello >> puts "hello" Method definition >> end >> end => nil >> o = MyClass.new New instance => #<MyClass:0x1036160d0> >> o.say_hello hello Invocation of method => nil
    • 23. No such method? • What if we invoke a method that doesn’t exist? >> o.say_goodbye NoMethodError: undefined method `say_goodbye' for #<MyClass: 0x1036160d0> from (irb):17
    • 24. method_missing >> class MyClass >> def method_missing(name) >> puts "You tried to execute the '#{name}' method. Too bad!" >> end >> end => nil >> o.say_goodbye You tried to execute the 'say_goodbye' method. Too bad! => nil
    • 25. method_missing >> class MyClass Symbol with method name >> def method_missing(name) >> puts "You tried to execute the '#{name}' method. Too bad!" >> end >> end => nil >> o.say_goodbye You tried to execute the 'say_goodbye' method. Too bad! => nil
    • 26. Method search order • Ruby looks for a matching method in the object’s class • If none is found, it tries in each ancestor class, in order • The class method “ancestors” returns an array of classes (and modules) • If no match found, invokes method_missing
    • 27. self • The “self” keyword is built into Ruby • It refers to the current object — the default receiver of messages • Knowing the value of “self” during each point of execution is important
    • 28. Inheritance! • Every object has a class • Every class (other than Object) has a superclass • We’ll look for methods in every parent class until we find a match or die trying
    • 29. Inheritance • When a class is defined, we can set its superclass class MyClass # inherits from Object class MyClass < YourClass • Single inheritance only!
    • 30. Superclass • How can we find the superclass? Ask the class! >> o.class => MyClass >> o.class.superclass => Object >> o.class.superclass.superclass => nil
    • 31. Methods are messages • When you say o.say_hello • You’re really invoking the “send” method: o.send(:say_hello)
    • 32. Mini-message sender >> def send_a_message >> s = ('a'..'z').to_a.join >> print "Enter a method name: " >> puts s.send(gets.chomp.to_sym) >> end
    • 33. Method protection • Methods are public by default • You may declare a method “public,” “private,” or “protected”
    • 34. public • Anyone can invoke the method o.a_method o.send(:a_method) # same thing o.a_method(an_argument) o.send(:a_method, an_argument)
    • 35. private • Only self can invoke private methods • In other words, you cannot invoke self.method_name or o.method_name • And certainly not o.send(:method_name) • Only instances of the class in which it was defined (and its subclasses) may use it
    • 36. protected • Not commonly used, in part because it’s hard to understand • Only if the sender and receiver of the message inherit the method from a common ancestor, may it be invoked
    • 37. Listing methods • Get an array of method names (as strings) o.methods o.public_methods # same as o.methods o.protected_methods o.private_methods
    • 38. What about data? • We said earlier that an object is data and a class pointer, and that methods sit on the class • So, where’s the data?
    • 39. Instance variables • Variables that are defined on an object, or “instance variables,” have a @ prefix • Often defined in the constructor • If accessed without being set, equal to nil • Unavailable outside of the object itself! • You must use methods to set or retrieve instance variables
    • 40. Instance variables >> o.instance_variables => ["@bar", "@foo"] >> o.instance_variable_get('@bar') => 2 >> o.instance_variable_set('@bar', 10) => 10 >> o.instance_variable_get('@bar') => 10
    • 41. Cool irb trick >> irb o >> instance_variables => ["@bar", "@foo"] >> @blah = 100 => 100 >> instance_variables => ["@blah", "@bar", "@foo"]
    • 42. Using instance variables class Person def initialize(first_name='', last_name='') @first_name = first_name @last_name = last_name end def name @first_name + ' ' + @last_name end end
    • 43. Defining getters • Define VARNAME as a method: def first_name @first_name end puts o.first_name
    • 44. Defining setters • Define VARNAME= as a method: def first_name=(value) @first_name = value end o.first_name = 5
    • 45. Attributes • Instead of defining setters and getters for all of your instance variables, create “attributes” attr_reader :foo # read-only attr_writer :bar # write-only attr_accessor :baz # read-write
    • 46. Attribute example class Person attr_accessor :first_name attr_accessor :last_name def initialize(first_name='', last_name='') @first_name = first_name @last_name = last_name end end
    • 47. Attribute example class Person attr_accessor :first_name attr_accessor :last_name def initialize(first_name='', last_name='') @first_name = first_name Still need to initialize @last_name = last_name our variables end end
    • 48. The story so far • Data is private, stored in @variables • Access to data is handled via methods • Methods are on an object’s class, and can be kept private (but are public by default) • The first matching method in the class’s ancestry is invoked • No match? method_missing or exception
    • 49. Wait a second... • When I use ActiveRecord, I say Person.find(:all) • What does that mean? How does that fit into what we already know?
    • 50. Person.find • Person.find is a method • Methods are defined on the class of the object • Person is an instance of Class • So Person’s methods are defined in Class? • No, but that’s not a bad guess!
    • 51. Indeed, we can do that >> class Person >> end => nil >> Person.blah NoMethodError: undefined method `blah' for Person:Class from (irb):33 from :0
    • 52. Class methods >> class Class >> def blah >> puts "blah!" >> end >> end => nil >> Person.blah blah! => nil >> Fixnum.blah blah! => nil
    • 53. Class methods >> class Class Open up the Class class >> def blah >> puts "blah!" and define a method >> end >> end => nil >> Person.blah blah! => nil >> Fixnum.blah blah! => nil
    • 54. Class methods >> class Class Open up the Class class >> def blah >> puts "blah!" and define a method >> end >> end => nil >> Person.blah Yes, we can define blah! class methods this way => nil >> Fixnum.blah blah! => nil
    • 55. Class methods >> class Class Open up the Class class >> def blah >> puts "blah!" and define a method >> end >> end => nil >> Person.blah Yes, we can define blah! class methods this way => nil >> Fixnum.blah blah! Er, if we want them => nil to be defined for all classes
    • 56. Hmm. • Class methods exist. • Methods are defined on an object’s class. • We know that Person.find isn’t defined on Class, because it is specific to ActiveRecord. • So where are class methods for Person defined?
    • 57. Singleton methods • Not the “singleton” design pattern! • A very unfortunate term • Define a method on an object, not a class • Occasionally useful for specific needs • Important as a tool for understanding
    • 58. Singleton example >> a = "hello" >> def a.say_something(something) >> puts something >> end >> a.say_something("hello") => hello >> "another_string".say_something("hello") NoMethodError: undefined method `say_something' for "another_string":String from (irb):47 from :0
    • 59. Singleton example >> a = "hello" >> def a.say_something(something) >> puts something >> end >> a.say_something("hello") => hello >> "another_string".say_something("hello") NoMethodError: undefined method `say_something' for "another_string":String from (irb):47 from :0
    • 60. Singleton example >> a = "hello" >> def a.say_something(something) >> puts something >> end Notice the method is >> a.say_something("hello") defined on a! => hello >> "another_string".say_something("hello") NoMethodError: undefined method `say_something' for "another_string":String from (irb):47 from :0
    • 61. Singleton methods • We add a method to a particular instance • But wait — methods only exist on classes • What the heck is going on here?
    • 62. Eigenclasses Object String Class is String a
    • 63. Eigenclasses Object String Class is String a
    • 64. Eigenclasses Object String Class is String Eigenclass a
    • 65. Eigenclasses Object String Class is String Eigenclass New class in the middle a
    • 66. Eigenclasses Object String Class is String Eigenclass New class in the middle a Singleton method is defined here
    • 67. Eigenclasses?!? • Also known as “ghost classes” — each object has its own eigenclass for private method storage • When you define a singleton method on an object, you’re creating an eigenclass that sits between the object and its class • Singleton methods are defined in the eigenclass
    • 68. Singleton override >> a = 'abc' >> a.reverse => "abc" => "ABC" >> b = 'def' >> b.reverse => "def" => "fed" >> def a.reverse >> b = a >> upcase => "abc" >> end >> b.reverse => nil => "ABC"
    • 69. Defining class methods • We define a singleton method by naming both the object and the method name: >> a = "hello" >> def a.say_something(something) >> puts something >> end
    • 70. Defining class methods • So we can define a class method by naming both the object and the method name: >> def Person.say_something(something) >> puts something >> end => nil >> Person.say_something('hello') hello => nil
    • 71. Instance vs. class methods • Rule: Methods for an object reside in its class • Methods for p (an instance of Person) are defined in Person • Methods for Person — class methods — are defined in Person’s eigenclass • Eigenclass of a class == “metaclass”
    • 72. Define class methods, 1 >> class Person >> def Person.foo >> "foo" >> end >> end => nil >> Person.foo => "foo"
    • 73. Define class methods, 1 >> class Person >> def Person.foo Defining on Person >> "foo" >> end >> end => nil >> Person.foo => "foo"
    • 74. Define class methods, 2 >> class Person >> def self.bar >> "bar" >> end >> end => nil >> Person.bar => "bar"
    • 75. Define class methods, 2 >> class Person >> def self.bar “self” in this >> "bar" context is Person >> end >> end => nil >> Person.bar => "bar"
    • 76. Define class methods, 3 >> class Person >> class << self >> def baz >> "baz" >> end >> end >> end => nil >> Person.baz => "baz"
    • 77. Define class methods, 3 >> class Person >> class << self Add to Person’s >> def baz eigenclass! >> "baz" >> end >> end >> end => nil >> Person.baz => "baz"
    • 78. Why do we care? • Why should I care about eigenclasses? • How does this affect me? • Couldn’t you think of a sillier name?
    • 79. It’s really important • Once you understand eigenclasses, you basically understand the entire Ruby object model • There are no exceptions to this rule of how things work • Suddenly, instance methods, class methods, and modules fall into place
    • 80. Oh, and by the way • We still haven’t explained how we defined Person.find • We know how to define a class method on a single class • But how do we define a class method for anything inheriting from ActiveRecord::Base?
    • 81. Answer • Define it on the eigenclass of the base class! >> class A >> class << self >> def boo >> "boo" >> end >> end >> end => nil
    • 82. That’s right: • OK, I admit it: Ruby is a bit sneaky here. • The superclass of the eigenclass of an object is the object’s class. • But the superclass of a class’s eigenclass is the eigenclass of the class’s superclass. • Or if you prefer: The superclass of the metaclass is the metaclass of the superclass.
    • 83. More on Eigenclasses Class Eigenclass of ActiveRecord::Base Class is Class Person
    • 84. More on Eigenclasses Class Class is Class Eigenclass of ActiveRecord::Base Person
    • 85. More on Eigenclasses Class Class is Class Eigenclass of ActiveRecord::Base Eigenclass Person
    • 86. More on Eigenclasses Class Class is Class Eigenclass of ActiveRecord::Base Eigenclass New class in the middle Person
    • 87. More on Eigenclasses Class Class is Class Eigenclass of ActiveRecord::Base Eigenclass New class in the middle Person “find” is defined here
    • 88. More on Eigenclasses Class Class is Class Eigenclass of ActiveRecord::Base Eigenclass New class in the middle Person “find” is defined here
    • 89. Unhiding eigenclasses class Object def eigenclass class << self self end end end
    • 90. Congratulations! • You’ve made it through the hard part • Now we can move onto modules!
    • 91. Modules • Modules have two uses: • Namespaces • Keep related code together, for inclusion as a whole later on
    • 92. Modules vs. Classes • Both are capitalized (i.e., they’re constants) • Both can contain methods • Classes are modules (but modules are not classes) • They may contain constants • “self” inside refers to the module/class
    • 93. Modules vs. classes • Regular (instance) methods defined in a module cannot be accessed directly • Module methods defined in a module may be accessed just like class methods • They’re also defined just like class methods
    • 94. Module methods, 1 >> module Blah >> def Blah.foo >> "foo" >> end >> end => nil >> Blah.foo => "foo"
    • 95. Module methods, 1 >> module Blah >> def Blah.foo Defining on Blah >> "foo" >> end >> end => nil >> Blah.foo => "foo"
    • 96. Module methods, 2 >> module Blah >> def self.foo >> "foo" >> end >> end => nil >> Blah.foo => "foo"
    • 97. Module methods, 2 >> module Blah >> def self.foo self here is Blah >> "foo" >> end >> end => nil >> Blah.foo => "foo"
    • 98. Module methods, 3 >> module Blah >> class << self >> def baz >> "baz" >> end >> end >> end => nil >> Blah.baz => "baz"
    • 99. Module methods, 3 >> module Blah >> class << self Add to Blah’s >> def baz eigenclass! >> "baz" >> end >> end >> end => nil >> Blah.baz => "baz"
    • 100. Constants in modules >> Math::E => 2.71828182845905 >> Math::PI => 3.14159265358979 >> Math.PI NoMethodError: undefined method `PI' for Math:Module from (irb):99
    • 101. Constants in modules >> Math::E => 2.71828182845905 >> Math::PI => 3.14159265358979 >> Math.PI Methods aren’t constants! NoMethodError: undefined method `PI' for Math:Module from (irb):99
    • 102. Nested modules >> module Stuff >> module Things >> def self.hello >> "hello" >> end >> end >> end => nil >> Stuff::Things.hello => "hello"
    • 103. Nested modules >> module Stuff >> module Things >> def self.hello >> "hello" >> end >> end >> end => nil >> Stuff::Things.hello => "hello"
    • 104. Nested modules >> module Stuff >> module Things >> def self.hello >> "hello" >> end >> end >> end :: is for namespaces, => nil . is for method calls >> Stuff::Things.hello => "hello"
    • 105. include • Modules are truly useful because you can “include” their methods into a class • This is sometimes known as “mix-ins” — you mix the methods from a module into your current class
    • 106. Inclusion rules • “include” any defined module into any class • The module is added to the ancestor chain, right above the class itself • The module’s methods become instance methods for your class — because instances get methods from their class!
    • 107. include >> module Foo >> def yikes >> "yikes!" >> end >> end >> class Person >> include Foo >> end >> Person.new.yikes => "yikes!"
    • 108. include >> module Foo >> def yikes >> "yikes!" >> end >> end >> class Person >> include Foo >> end >> Person.new.yikes Modules are objects, => "yikes!" so you don’t use quotes
    • 109. How does this work? >> class Person >> end >> class Person => nil >> include MyModule >> end >> Person.ancestors => Person => [Person, Object, Wirble::Shortcuts, >> Person.ancestors PP::ObjectMixin, => [Person, MyModule, Kernel] Object, Wirble::Shortcuts, >> module MyModule PP::ObjectMixin, >> end Kernel] => nil
    • 110. How does this work? >> class Person >> end >> class Person => nil >> include MyModule >> end >> Person.ancestors => Person => [Person, Object, Wirble::Shortcuts, >> Person.ancestors PP::ObjectMixin, => [Person, MyModule, Kernel] Object, Wirble::Shortcuts, >> module MyModule PP::ObjectMixin, MyModule was added to >> end Kernel] Person’s ancestors => nil
    • 111. More than one include >> Person.ancestors => [Person, MyModule, Object, Wirble::Shortcuts, PP::ObjectMixin, Kernel] >> module MyModule2 >> end => nil >> class Person >> include MyModule2 >> end => Person >> Person.ancestors => [Person, MyModule2, MyModule, Object, Wirble::Shortcuts, PP::ObjectMixin, Kernel]
    • 112. More than one include >> Person.ancestors => [Person, MyModule, Object, Wirble::Shortcuts, PP::ObjectMixin, Kernel] >> module MyModule2 >> end => nil >> class Person include adds the new module >> >> include MyModule2 end right after the class itself => Person >> Person.ancestors => [Person, MyModule2, MyModule, Object, Wirble::Shortcuts, PP::ObjectMixin, Kernel]
    • 113. Implications • Import as many modules as you want! • Sort of like multiple inheritance • The most recent import “wins” • Modules cannot override previously defined methods in a class
    • 114. Enumerable • The most popular mixin module is Enumerable • If your class defines “each”, then you get a huge number of methods as a result
    • 115. Class methods • What if you want a module to define class methods? • Import the module into the eigenclass, of course!
    • 116. Regular include >> module MyModule >> i = InstanceInclude.new >> def hello => #<InstanceInclude: >> "hello" 0x103624220> >> end >> i.hello >> end => "hello" => nil >> InstanceInclude.hello >> class InstanceInclude NoMethodError: undefined >> include MyModule method `hello' for >> end InstanceInclude:Class => InstanceInclude from (irb):11
    • 117. Eigenclass include >> class ClassInclude >> class << self >> include MyModule >> end >> end => #<Class:ClassInclude> >> c = ClassInclude.new => #<ClassInclude:0x1035f20e0> >> c.hello NoMethodError: undefined method `hello' for #<ClassInclude:0x1035f20e0> >> ClassInclude.hello => "hello"
    • 118. Eigenclass include >> class ClassInclude >> class << self >> include MyModule >> end >> end => #<Class:ClassInclude> Here the eigenclass is “self,” so >> c = ClassInclude.new => #<ClassInclude:0x1035f20e0> >> c.hello include imports the module as class methods NoMethodError: undefined method `hello' for #<ClassInclude:0x1035f20e0> >> ClassInclude.hello => "hello"
    • 119. extend • Alternatively, we can use “extend,” which does the same thing — it includes the module on the eigenclass • In other words, it imports the methods from the module as class methods
    • 120. extend >> class ExtendInclude >> extend MyModule >> end => ExtendInclude >> e = ExtendInclude.new => #<ExtendInclude:0x1035d22b8> >> e.hello NoMethodError: undefined method `hello' for #<ExtendInclude:0x1035d22b8> from (irb):24 >> ExtendInclude.hello => "hello"
    • 121. Including and extending • This is pretty magical, but useful • When you include a module, the module’s “included” method is invoked — and the class that invoked it is passed as a parameter
    • 122. included >> module Squealer >> def self.included(base) >> puts "Squealer was just included by '#{base.to_s}'!" >> end >> end => nil >> class Includer >> include Squealer >> end Squealer was just included by 'Includer'! => Includer
    • 123. module Foo def self.included(base) base.extend(ClassMethods) end module ClassMethods def bar puts 'class method' end end def foo puts 'instance method' end end
    • 124. lib in Rails • All of the files in the “lib” directory are evaluated at startup time • This means that you can define any number of modules in those files • Put common functionality there — put common methods into a module, and then include those methods in your classes
    • 125. irb addon: looksee • gem install looksee • require 'looksee/shortcuts' # in .irbrc • “lp varname” shows you which methods came from which modules and classes • Shows eigenclasses and metaclasses • Useful and fun... but it apparently doesn’t work with jruby. Sigh.
    • 126. Contacting me • Call me in Israel: 054-496-8405 • Call me in the US: 847-230-9795 • E-mail me: reuven@lerner.co.il • Interrupt me: reuvenlerner (Skype/AIM)