如何在 Ruby 中为几何形状(点、线、正方形、三角形等)创建 类
How to create classes for geometric shapes (points, lines, square, triangle, etc.) in Ruby
我们被要求通过 classes 创建几何形状。我们必须创建:
- 一个点class.
- A Line class(线 - 当两点相连时)。
- 一个正方形class.
我创建了一个点 class,具有可访问的坐标 (2D):
class Point
attr_accessor :x, :y
def initialize
@x = 10
@y = 10
end
def x=(value)
@x = value
end
def x()
@x
end
def y=(value)
@y = value
end
def y()
@y
end
end
而且,我想创建一个新点class:
p = Point.new
p.x = 1
p.y = 5
print p # -> #<Point:0x007f9463089cc0>
因此,我有这样的事情:
#<Point:0x007f9463089cc0>
这是什么意思?
如果我print p.x, p.y
那么我会得到一个可以理解的结果:
print p.x, ", ", p.y # -> 1, 5
如何在屏幕上理解这个结果?
创建点、线和几何形状在实际编程工作中有什么用吗?
您不需要编写 setter 和 getter 方法:
def x=(value)
@x = value
end
def x()
@x
end
def y=(value)
@y = value
end
def y()
@y
end
这是因为您可以使用:
attr_accessor :x, :y
并且 attr_accessor
会为您做到这一点。
您可能希望在构造函数中允许一些灵活性。您的 initialize
方法允许传递 x
和 y
的值,如果未传递任何值,则默认为 10,因此您可以这样做:
def initialize(x = 10, y = 10)
@x = x
@y = y
end
这样,你会得到:
p1 = Point.new
puts p.x # => 10
puts p.y # => 10
p2 = Point.new(15, 20)
puts p.x # => 15
puts p.y # => 20
注意 p1
我没有传递任何参数,但 x
和 y
都按预期设置了,因为我们在方法中为它们设置了默认值定义,这里:
def initialize(x = 10, y = 10)
关于你为什么看到这个的问题:
p = Point.new
p.x = 1
p.y = 5
print p # -> #<Point:0x007f9463089cc0>
Point:0x007fa003885bf8
表示您在变量 p
中有一个 class Point
的实例。默认情况下 Ruby 将在您尝试打印对象时调用对象的 to_s
方法,因为在您的情况下您没有定义该方法,它将通过继承链查看谁定义了该方法.事实证明,该方法是在所有 Ruby 对象隐式继承自的对象 class 中找到的,并且该方法的默认行为是打印 class 的名称,后跟实例的 ID在内存中,格式为:
#<ClassName:MemoryID>
参见:http://ruby-doc.org/core-2.3.1/Object.html#method-i-to_s
如果你想改变它,那么你可以将 to_s
覆盖为这样的东西:
def to_s
"Point #{x},#{y}"
end
这样你会得到:
puts Point.new # => "Point 10,10"
没什么问题。
#<Point:0x007f9463089cc0>
只是表示它是classPoint
的实例(#<>
部分),对象ID为0x007f9463089cc0
。对象 ID 是 Ruby 的解释器查找每个对象的标识符,很像内存地址。
虽然一切都很好,但 Ruby 中总有一种方法可以减少代码。例如:
class Point
attr_accessor :x, :y
def initialize(x = 10, y = 10)
@x, @y = x, y
end
end
甚至:
Point = Struct.new(:x, :y)
因为你要声明attr_accessor :x, :y
您实际上不需要为 x
和 y
定义 getter 和 setter,
所以你的 class 可以简化为:
class Point
attr_accessor :x, :y
def initialize
@x = 10
@y = 10
end
end
你也可以添加一个to_s
方法到Point:
class Point
attr_accessor :x, :y
def initialize
@x = 10
@y = 10
end
def to_s
"(#{x}, #{y})"
end
end
所以你可以使用 puts p
并在你这样做时得到输出 (10, 10)
:
p = Point.new
puts p
(10, 10)
我更喜欢使用puts
而不是print
,因为它在输出后插入一个换行符,而且看起来更具可读性。
在 to_s
中,我正在使用 Ruby 的字符串插值 "#{}"
为您的 Point 实例构建一个不错的输出。
方法print
和puts
输出to_s
的结果,p
输出inspect
的结果。除非您覆盖这些方法,否则默认情况下,自定义 class 继承 Object
returns 您获得的形式 #<class_name:object_id>
。如果你想要一些其他的输出,覆盖这些方法,例如
class Point
def to_s
"#@x,#@y"
end
end
...
print p
我们被要求通过 classes 创建几何形状。我们必须创建:
- 一个点class.
- A Line class(线 - 当两点相连时)。
- 一个正方形class.
我创建了一个点 class,具有可访问的坐标 (2D):
class Point
attr_accessor :x, :y
def initialize
@x = 10
@y = 10
end
def x=(value)
@x = value
end
def x()
@x
end
def y=(value)
@y = value
end
def y()
@y
end
end
而且,我想创建一个新点class:
p = Point.new
p.x = 1
p.y = 5
print p # -> #<Point:0x007f9463089cc0>
因此,我有这样的事情:
#<Point:0x007f9463089cc0>
这是什么意思?
如果我print p.x, p.y
那么我会得到一个可以理解的结果:
print p.x, ", ", p.y # -> 1, 5
如何在屏幕上理解这个结果?
创建点、线和几何形状在实际编程工作中有什么用吗?
您不需要编写 setter 和 getter 方法:
def x=(value)
@x = value
end
def x()
@x
end
def y=(value)
@y = value
end
def y()
@y
end
这是因为您可以使用:
attr_accessor :x, :y
并且 attr_accessor
会为您做到这一点。
您可能希望在构造函数中允许一些灵活性。您的 initialize
方法允许传递 x
和 y
的值,如果未传递任何值,则默认为 10,因此您可以这样做:
def initialize(x = 10, y = 10)
@x = x
@y = y
end
这样,你会得到:
p1 = Point.new
puts p.x # => 10
puts p.y # => 10
p2 = Point.new(15, 20)
puts p.x # => 15
puts p.y # => 20
注意 p1
我没有传递任何参数,但 x
和 y
都按预期设置了,因为我们在方法中为它们设置了默认值定义,这里:
def initialize(x = 10, y = 10)
关于你为什么看到这个的问题:
p = Point.new
p.x = 1
p.y = 5
print p # -> #<Point:0x007f9463089cc0>
Point:0x007fa003885bf8
表示您在变量 p
中有一个 class Point
的实例。默认情况下 Ruby 将在您尝试打印对象时调用对象的 to_s
方法,因为在您的情况下您没有定义该方法,它将通过继承链查看谁定义了该方法.事实证明,该方法是在所有 Ruby 对象隐式继承自的对象 class 中找到的,并且该方法的默认行为是打印 class 的名称,后跟实例的 ID在内存中,格式为:
#<ClassName:MemoryID>
参见:http://ruby-doc.org/core-2.3.1/Object.html#method-i-to_s
如果你想改变它,那么你可以将 to_s
覆盖为这样的东西:
def to_s
"Point #{x},#{y}"
end
这样你会得到:
puts Point.new # => "Point 10,10"
没什么问题。
#<Point:0x007f9463089cc0>
只是表示它是classPoint
的实例(#<>
部分),对象ID为0x007f9463089cc0
。对象 ID 是 Ruby 的解释器查找每个对象的标识符,很像内存地址。
虽然一切都很好,但 Ruby 中总有一种方法可以减少代码。例如:
class Point
attr_accessor :x, :y
def initialize(x = 10, y = 10)
@x, @y = x, y
end
end
甚至:
Point = Struct.new(:x, :y)
因为你要声明attr_accessor :x, :y
您实际上不需要为 x
和 y
定义 getter 和 setter,
所以你的 class 可以简化为:
class Point
attr_accessor :x, :y
def initialize
@x = 10
@y = 10
end
end
你也可以添加一个to_s
方法到Point:
class Point
attr_accessor :x, :y
def initialize
@x = 10
@y = 10
end
def to_s
"(#{x}, #{y})"
end
end
所以你可以使用 puts p
并在你这样做时得到输出 (10, 10)
:
p = Point.new
puts p
(10, 10)
我更喜欢使用puts
而不是print
,因为它在输出后插入一个换行符,而且看起来更具可读性。
在 to_s
中,我正在使用 Ruby 的字符串插值 "#{}"
为您的 Point 实例构建一个不错的输出。
方法print
和puts
输出to_s
的结果,p
输出inspect
的结果。除非您覆盖这些方法,否则默认情况下,自定义 class 继承 Object
returns 您获得的形式 #<class_name:object_id>
。如果你想要一些其他的输出,覆盖这些方法,例如
class Point
def to_s
"#@x,#@y"
end
end
...
print p