0

我正在编写一个包含 4 个类(点、形状、矩形、圆)的程序。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​​ 方式?

4

2 回答 2

4

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

尝试这个:

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

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

如果在orx中没有x定义,期望得到什么?继承自?ShapeCircleShapePoint

编辑:

@center要访问保存x和值的实例变量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

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

于 2012-11-16T01:22:06.680 回答
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调用super.x将失败,因为super只表示它被调用的当前覆盖的方法,而不是整个超类。现在,要访问超类的属性,您只需调用@x.to_sself.x.to_s因为超类的属性属于子类。

于 2012-11-16T01:46:58.980 回答