我正在编写一个包含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方式?
答案 0 :(得分:4)
调用super
发送父类的to_s
方法,结果(字符串),然后发送x
,y
等方法,这些方法字符串不存在。
试试这个:
def to_s
"Circle: [(#{x},#{y}) #{radius}]"
end
Ruby具有隐式字符串插值,这意味着在双引号字符串中,#{...}
内的任何内容都将自动呈现为字符串。
如果x
或x
中没有定义Shape
,那么期望从Circle
得到什么? Shape
是否继承自Point
?
修改强>
要访问包含@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
然后在您的实例中,您可以直接致电x
和y
,它们会自动转发到@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
,因为超类的属性属于子类。