我的to_s方法对继承的Circle类有什么问题?

时间:2012-11-16 01:14:33

标签: ruby oop inheritance

我正在编写一个包含4个类(Point,Shape,Rectangle,Circle)的程序。 Rectangle和Circle继承自Shape,其中包含形状中心的信息(字段)。我正在尝试为Circle类编写一个to_s方法,它应该打印出来,如下所示:

  

圈子:[(1,2),3]

(1,2)为中心,3为半径。这就是我对to_s方法所拥有的:

def to_s
  "Circle: [(" + super.x.to_s + ", " + super.y.to_s + "), " + 
    radius.to_s + "]"
end

我收到错误“没有这样的方法'x'错误”,我明白这是因为Shape没有'x'方法(它在Point中)。我尝试了一些类似super.center.y.to_s的长方法链接,但是它有自己的问题。这样做的正确方法是什么。即良好的编程风格,面向对象的方式和ruby方式?

2 个答案:

答案 0 :(得分:4)

调用super发送父类的to_s方法,结果(字符串),然后发送xy等方法,这些方法字符串不存在。

试试这个:

def to_s
  "Circle: [(#{x},#{y}) #{radius}]"
end

Ruby具有隐式字符串插值,这意味着在双引号字符串中,#{...}内的任何内容都将自动呈现为字符串。

如果xx中没有定义Shape,那么期望从Circle得到什么? Shape是否继承自Point

修改

要访问包含@centerx值的实例变量y,您有几个选项。这是最基本的:

class Shape
  attr_accessor :center

  def initialize(point)
    @center = point
  end
end

class Circle

  def initialize(point, radius)
    super(point) # this runs Shape's initialize method
    @radius = radius
  end

  def to_s
    "Circle: [(#{center.x},#{center.y}) #{radius}]"
  end
end

另一种选择是使用内置的Forwardable模块:

require 'forwardable'
class Shape
  extend Forwardable
  def_delegators :@center, :x, :y
  #...
end

然后在您的实例中,您可以直接致电xy,它们会自动转发到@center,在这种情况下,“Circle:[(#{x}} ,#{y})#{radius}]“字符串将起作用。

答案 1 :(得分:0)

在ruby中,super只是一个表示重写方法而不是超类本身的方法。

示例:

class A
    def to_s
        'A'
    end
end

p A.new.to_s #=> returns 'A'

class B < A
    def to_s
        super + 'with' + 'B'
    end
end

p B.new.to_s #=> returns 'A with B'

如果你没有这样做,调用super只会调用A.to_s而不是A本身,以便A有一个属性x来调用{{ 1}}会失败,因为super.x只表示它被调用的当前被重写的方法,而不是整个超类。现在,要访问超类的属性,您只需调用super@x.to_s,因为超类的属性属于子类。