Ruby挑战 - 形状继承

时间:2013-10-31 20:11:52

标签: ruby

学习Ruby。我接受了这个代码挑战:

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

这些类还应该能够调用一个can_fit?方法来评估两个形状,并根据另一个形状内部的一个形状返回true或false。

所以我已经很好地创建了形状类,我正在计算方形,矩形和圆形的区域。

但我完全被can_fit?方法所困扰。我应该将它包含在Shape类中,但是如果我们使用区域进行比较,我如何比较Shape类中的一个形状是否适合另一个形状,Shape不会无法访问区域?

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

5 个答案:

答案 0 :(得分:1)

Ruby并不介意Shape没有区域方法。它只关心对象在评估瞬间的行为方式。对于下面的can_fit?方法,self是Square的实例,other_shape是圆的实例。两者都有面积法。很好!如果other_shape完全是其他对象,只要它具有area方法,它仍然可以正常工作。

E.g。 (在这里忽略'计算'!)

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 

答案 1 :(得分:0)

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

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

我说“天真”,因为我不知道你是否可以旋转这些形状或不适合它们。(4x6矩形 适合7x5矩形,但只有你'能够旋转矩形。)如果是这样,那么你可能需要计算其他尺寸,比如矩形的对角线。

我知道你在做Ruby,但你可能需要注意看看Ruby中的继承意味着什么。 Scott Meyers关于C ++的一本书使用了这个确切的例子来说明数学模型(“正方形也是一个矩形”)如何在C ++继承面前崩溃。来自类Rectangle的派生类Square不能用与数学定义相同的优雅来表达。我不知道Ruby的那个答案,但你会想看看它(只要你正在学习)。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

假设我们有

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

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

def self_check
  puts self
end

将此方法发送到cr,我们会收到以下信息:

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是否为真的原因。

答案 4 :(得分:0)

你需要定义一个can_fit吗?类形状中使用self.area与other_shape.area相比的方法

因为每个班级都有一个区域:

def can_fit?(other_shape)
  self.area > other_shape.area
end