0

学习红宝石。我收到了这个代码挑战:

创建类来表示正方形、矩形和圆形。您应该能够计算每个形状的面积。(还有一部分是关于能够设置颜色以及继承默认颜色,但这不是我难以理解的部分,所以我不会在此处包含规格。)

这些类还应该能够调用一种can_fit?方法,该方法评估两个形状并根据一个形状适合另一个形状返回真或假。

所以我已经很好地创建了形状类,并且很好地计算了正方形、矩形和圆形的面积。

但我完全被这个can_fit?方法难住了。我应该将它包含在课堂上,但是如果我们使用区域进行比较并且无法访问区域,我该Shape如何比较一个形状是否适合课堂中的另一个形状?ShapeShape

class Shape
  attr_accessor :color
  def initialize(color="Red")
    @color = color
  end

  def can_fit?(shape)
    DEFINE METHOD
  end

end

class Rectangle < Shape

attr_accessor :color, :shape, :width, :height

def initialize(width, height, color="Red")
  super(color)
  @width = width
  @height = height
end

def area
  @width * @height
end

end

class Square < Rectangle

  def initialize(width, color= "Red")
    super(width, width, color)
  end

end

class Circle < Shape
attr_accessor :color, :shape, :radius

def initialize(radius, color= "Red")
  super(color)
  @radius = radius
end

def area
  Math::PI * (radius ** 2)
end

end

RSpec 测试:

describe "Shape" do
   describe "can_fit?" do
     it "should tell if a shape can fit inside another shape" do

     class A < Shape
       def area
         5
       end
     end
     class B < Shape
       def area
        10
       end
     end
     a = A.new
     b = B.new
     b.can_fit?(a).should eq(true)
     a.can_fit?(b).should eq(false)
  end
end
4

5 回答 5

1

Ruby 不介意Shape没有 area 方法。它只关心对象在评估时的行为。在以下can_fit?方法的情况下,self是 Square 的一个实例,并且other_shape是 circle 的一个实例。两者都有面积方法。很好!如果other_shape完全是其他对象,只要它有area方法,它仍然可以工作。

例如(忽略这里的“计算”!)

2.0.0-p195 :001 > class Shape
2.0.0-p195 :002?>   def can_fit? other_shape
2.0.0-p195 :003?>     area > other_shape.area
2.0.0-p195 :004?>   end
2.0.0-p195 :005?> end
 => nil 
2.0.0-p195 :006 > class Square < Shape
2.0.0-p195 :007?>   def area
2.0.0-p195 :008?>     2
2.0.0-p195 :009?>   end
2.0.0-p195 :010?> end
 => nil 
2.0.0-p195 :011 > class Circle < Shape
2.0.0-p195 :012?>   def area
2.0.0-p195 :013?>     1
2.0.0-p195 :014?>   end
2.0.0-p195 :015?> end
 => nil 
2.0.0-p195 :016 > Square.new.can_fit? Circle.new
 => true 

接着...

2.0.0-p195 :017 > class Cat # doesn't inherit from anything
2.0.0-p195 :018?>   def area
2.0.0-p195 :019?>     1.5
2.0.0-p195 :020?>   end
2.0.0-p195 :021?> end
 => nil 
2.0.0-p195 :022 > Square.new.can_fit? Cat.new
 => true 
于 2013-10-31T21:03:25.680 回答
0

是否可以使用定义的方法创建一个新类 Area 并将 Shape 调用到其中?只是一个想法

于 2013-10-31T20:37:13.703 回答
0

一个天真的解决方案是查看一个形状的高度和宽度是否小于或等于您尝试放入第一个形状的形状的高度和宽度。

对于圆,宽度和高度都是圆的直径。

我说“天真”是因为我不知道你是否可以旋转这些形状以适应它们。(一个 4x6 矩形确实适合一个 7x5 矩形,但前提是你能够旋转矩形。)如果是这样,那么您可能需要计算其他尺寸,例如矩形的对角线。

我知道您正在使用 Ruby,但您可能需要仔细了解 Ruby 中继承的确切含义。Scott Meyers 的一本关于 C++ 的书使用这个确切的例子来展示数学模型(“正方形也是矩形”)在面对 C++ 继承时是如何崩溃的。从类 Rectangle 派生的类 Square 不能像数学定义那样优雅地表达。我不知道 Ruby 的答案,但你会想看看它(只要你在学习)。

于 2013-10-31T20:18:16.437 回答
0

你需要定义一个can_fit?与 other_shape.area 相比,使用 self.area 的 Class Shape 中的方法

因为您已经为每个班级准备了一个区域:

def can_fit?(other_shape)
  self.area > other_shape.area
end
于 2013-11-01T01:39:07.123 回答
0

假设我们有

c = Circle.new(2)
r = Rectangle.new(2,3)

现在让我们将以下方法添加到class Shape

def self_check
  puts self
end

将此方法发送到cand r,我们得到以下信息:

c.self_check # => #<Circle:0x007fd71927fc98 @color="Red", @radius=1> 
r.self_check # => #<Rectangle:0x007fd71925e368 @color="Red", @width=2, @height=3>

因此,即使self_check在父类中,self也是调用它的子类的实例。这意味着可以can_fit?(other_shape)访问形状实例self以及参数other_shape。因此,我们可以执行以下操作 1:

def can_fit?(other_shape)
  case self
  when Circle
    case other_shape
    when Circle
      self.radius <= other_shape.radius
    when Rectancle, Square
      self.radius <= [other_shape.width, other_shape.height].min
    end
  when Rectangle
    case other_shape
    when Circle
    ...
    ...

要查看特定实例实例c是否适合特定矩形实例r,我们将执行:

c.can_fit?(r)

1 请注意,case 语句使用===运算符,而不是构造==使用的运算符。if/then这就是为什么case可以评估是否self === Circle为真。

于 2013-10-31T21:45:26.673 回答