1 / 19

Ruby Classes

Ruby Classes. and other languages… . Objects and Classes. What does that mean?. Every value in Ruby is (or behaves like) an object 2.times { puts “hey”} Objects are instances of classes Instance variables are strictly encapsulated. Object creation. def initialize(x, y, z=nil)

corin
Télécharger la présentation

Ruby Classes

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Ruby Classes and other languages…

  2. Objects and Classes What does that mean? • Every value in Ruby is (or behaves like) an object • 2.times { puts “hey”} • Objects are instances of classes • Instance variables are strictly encapsulated

  3. Object creation def initialize(x, y, z=nil) @x, @y, @z = x,y,z end • Every class inherits method new • calls allocateto get space (can’t override) • calls initializeto create instance variables • Often convenient to provide default parameters for initialize • Not covered: dup, clone, initialize_copy • Not covered: marshalling (create from serialized data)

  4. Simple Class class Cat def initialize(name, age) @name, @age = name, age end def to_s "(#@name, #@age)" end def name @name end def age @age end def name=(value) @name=value end def age=(value) @age=value end end c = Cat.new("Fluffy", 2) puts c puts c.name c.age=5 puts c.age new calls initialize to_s like toString getters and setters, called attributes last expression in function is return @ indicates instance variable always refer to self DO NOT declare outside of method

  5. Operator Overloading, etc. class Bottle attr_accessor :ounces attr_reader :label def initialize(label, ounces) @label = label @ounces = ounces end def add(other) Bottle.new(@label, @ounces+other.ounces) end def add!(other) @ounces += other.ounces other.ounces = 0 end def split(scalar) newOunces = @ounces / scalar @ounces -= newOunces Bottle.new(@label, newOunces) end def +(amount) Bottle.new(@label, @ounces + amount) end def to_s "(#@label, #@ounces)" end end b = Bottle.new("Tab", 16) puts b.label b.ounces = 20 puts "b is #{b}“ puts "result of b2 = b.split 4" b2 = b.split 4 puts "b is #{b}" puts "b2 is #{b2}“ puts "result of b3 = b.add(b2)" b3 = b.add(b2) puts "b3 is #{b3}“ puts "result of b.add!(b2)" b.add!(b2) puts "b is #{b}" puts "b2 is #{b2}“ puts "result of b4 = b3 + 10" b4 = b3 + 10 puts "b4 is #{b4}" attr is example of metaprogramming

  6. Duck Typing class Can attr_accessor :ounces def initialize(label, ounces) @label = label @ounces = ounces end def to_s "(#@label, #@ounces)" end end b = Bottle.new("Tab", 16) c = Can.new(“Coke", 12) b2 = b.add(c) puts "result of b2 = b.add(c)" puts "b2 is #{b2}“ cat = Cat.new b3 = b.add(cat) • If it walks like a duck and quacks like a duck, it must be a duck • any object with needed method will work • undefined method ‘ounces’ for <Cat> http://beust.com/weblog/2005/04/15/the-perils-of-duck-typing/

  7. Object Class Quick Ex: how does Java handle? x=1 x.instance_of? Fixnum => true x.instance_of? Numeric => false (even though subclass) x.is_a? Fixnum => true x.is_a? Numeric => true x.is_a? Comparable => true x.is_a? Object => true x.class == Fixnum => true x.class == Numeric => false

  8. Object Type • Class of an object doesn’t change • Type is more fluid… includes set of behaviors (methods it responds to) • i.e, Class != Type….whoaaa • respond_to?

  9. Object equality equal? checks addresses (like == in Java) for Object, == is synonym for equal? Most classes override == (like equal in Java)

  10. Equality Example class Bottle attr_accessor :ounces attr_reader :label def initialize(label, ounces) @label = label @ounces = ounces end def ==(other) return false if ! other.instance_of? Bottle return @ounces == other.ounces && @label == other.label end alias eql? == end # Can also has ounces class Can attr_accessor :ounces def initialize(label, ounces) @label = label @ounces = ounces end end b = Bottle.new("Tab", 16) b2 = Bottle.new("Tab", 16) b3 = Bottle.new("Tab", 12) b4 = Bottle.new("Coke", 16) puts "b.equal?(b2) #{b.equal?(b2)}" puts "b == b2 #{b == b2}" puts "b == b3 #{b == b3}" puts "b == b4 #{b == b4}“ puts "b.eql?(b2) #{b.eql?(b2)}" puts "b.eql?(b3) #{b.eql?(b3)}" c = Can.new("Tab", 16) puts "b == c #{b == c}"

  11. More object equality Other language with eql?/=== feature? • Numeric classes will do type conversions when used with== • eql? is like ==, but no type conversion • 1.eql? 1.0 • can alias eql? with == • === used with case statement • (1..10) === 5 # true, 5 is in range • /\d+/ === “123” # true, matches regex • String === “s” # true if s is instance of String

  12. Type conversions • Widening Conversions: can include at least approximations to all of the values of the original type. Examples (Java/C++) • byte to short, int, long, float or double • short to int, long, float or double • char to int, long, float or double • int to long, float or double • long to float or double • float to double • Narrowing conversions: cannot include all of the values of the original type • short to byte or char • char to byte or short • int to byte, short, or char • long to byte, short, char or int • float to byte, short, char, int or long • double to byte, short, char, int, long or float

  13. Type conversions – dangerous? Conversions should be used with care! Warnings should not just be ignored… Strongly typed language minimizes type conversions Even widening conversions may lose accuracy. Example: integers stored in 32 bits, 9 digits of precision. Floating point values also stored in 32 bits, only about 7 digits of precision (because of space used for exponent).

  14. Type-safe Methods class Bottle attr_accessor :ounces attr_reader :label def initialize(label, ounces) @label = label @ounces = ounces end def add(other) raise TypeError, "Bottle argument expected " unless other.is_a? Bottle Bottle.new(@label, @ounces+other.ounces) end def add2(other) raise TypeError, "Bottle argument expected " unless other.respond_to? :ounces Bottle.new(@label, @ounces+other.ounces) end def add3(other) Bottle.new(@label, @ounces+other.ounces) rescue raise TypeError, "Cannot add with an argument that doesn't have ounces" end def to_s "(#@label, #@ounces)" end end class Can attr_accessor :ounces def initialize(label, ounces) @label = label @ounces = ounces end def to_s "(#@label, #@ounces)" end end class Cat end b = Bottle.new("Tab", 16) c = Can.new("Coke", 12) puts "result of b2 = b.add(c)" b2 = b.add(c) puts "result of b2 = b.add2(c)" b2 = b.add2(c) puts "b2 is #{b2}" puts "result of b2 = b.add3(c)" b2 = b.add3(c) puts "b2 is #{b2}" cat = Cat.new puts "result of b2 = b.add3(cat)" b2 = b.add3(cat)

  15. More overloading class Bottle attr_accessor :ounces attr_reader :label def initialize(label, ounces) @label = label @ounces = ounces end def each yield @label yield @ounces end def [](index) case index when 0, -2 then @label when 1, -1 then @ounces when :label, "label" then @label when :ounces, "ounces" then @ounces end end end b = Bottle.new("Tab", 16) puts "using each" b.each {|x| puts x } puts "[ix]" puts b[0] puts b[-2] puts b[1] puts b[-1] puts "[field name]" puts b["label"] puts b[:label] puts b["ounces"] puts b[:ounces]

  16. Object Comparisons Implement <=> operator Like compareTo (-1, 0, 1 and nil if not comparable) Typically include Comparable module as a mixin Provides <, <=, ==, >=, >(defined in terms of <=>) Sometimes write == anyway (e.g., one may be case-sensitive, may be more efficient). Best to be consistent.

  17. Comparison example class Bottle include Comparable attr_accessor :ounces attr_reader :label def initialize(label, ounces) @label = label @ounces = ounces end def hash #based on Effective Java by Bloch code = 17 code = 37 * code + @label.hash code = 37 * code + @ounces.hash code end def <=>(other) return nil unless other.instance_of? Bottle @ounces <=> other.ounces end end b = Bottle.new("Tab", 16) b2 = Bottle.new("Tab", 12) b3 = Bottle.new("Coke", 16) b4 = Bottle.new("Tab", 16) puts "b == b2 #{b == b2}" puts "b < b2 #{b < b2}" puts "b > b2 #{b > b2}" puts "b == b3 #{b == b3}" puts "b == b4 #{b == b4}"

  18. Class Methods and variables class Bottle include Comparable attr_accessor :ounces attr_reader :label MAX_OUNCES = 64 @@numBottles = 0 def initialize(label, ounces) @label = label @@numBottles += 1 if ounces > MAX_OUNCES @ounces = MAX_OUNCES else @ounces = ounces end end def Bottle.sum(bottles) total = 0 bottles.each {|b| total += b.ounces } total end def to_s "(#@label, #@ounces)" end def self.report #class method puts "Number of bottles created: #@@numBottles" end end bottles = Array.new bottles[0] = Bottle.new("Tab", 16) bottles[1] = Bottle.new("Tab", 16) bottles[2] = Bottle.new("Coke", 16) bottles[3] = Bottle.new("Tab", 20) puts "Total ounces: #{Bottle.sum bottles}" b = Bottle.new("Sprite", 72) puts b Bottle.report Not covered: Class Instance Variables

  19. Topic Summary • Language Concepts • Classes • Instance variables • Object creation • Determine object type • Object equality • Object comparisons • Type conversions • Type safety • Class methods • Class variables • Ruby • new • to_s • duck typing

More Related