class Point attr_accessor :x, :y def initialize(x, y) @x = x @y = y end def dist0 Math.sqrt(@x * @x + @y * @y) end def dist0_getters Math.sqrt(x * x + y * y) end end class Point3D < Point att_accessor :z def initialize(x, y, z) super(x, y) @z = z end def dist0 d = super Math.sqrt(d * d + @z * @z) end def dist0_getters d = super Math.sqrt(d * d + z * z) end end # overriding can cause a method in the superclass # to call a method in the subclass!!! class PolarPoint < Point # since super not called, no x and y instance vars initialized def initialize(radius, angle) @radius = radius @angle = angle end def x @radius * Math.cos(@angle) end def y @radius * Math.sin(@angle) end def x= a @radius = Math.sqrt(a * a + y * y) @angle = Math.atan(y / a) self end def y= b @radius = Math.sqrt(y * y + b * b) @angle = Math.atan(b / y) self end def dist0 @radius end # dist0_getters already works!!! end # precise rules of dynamic dispatch # call to self.m in class C may actually call # method m in some subclass of C # define method lookup # rules for "looking things up" key part of PL semantics # e.g. lexical scope class A def even x puts "in even A" if x == 0 true else odd (x - 1) end end def odd x puts "in odd A" if x == 0 false else even (x - 1) end end end class B < A def even x puts "in even B" x % 2 == 0 end end class C < A def even x puts "in even C" false end end a1 = A.new.odd 7 puts "Q: 7 is odd? A: " + a1.to_s + "\n\n" a2 = B.new.odd 7 puts "Q: 7 is odd? A: " + a2.to_s + "\n\n" a3 = C.new.odd 7 puts "Q: 7 is odd? A: " + a3.to_s + "\n\n"