2016-02-20 67 views
3

我知道抽象类不是Ruby中的一个特性,当然这背后有一个哲学原因,但我想知道是否有办法解决通常使用其他语言(如C++和Java)中的抽象类来解决的问题。使用Ruby处理抽象类解决方案的正确方法是什么?

例如: 我需要三个类Triangle,SquareCircle。因为这些都是几何图形,所以我在考虑用抽象方法AbstractFigure编写一个抽象类get_area,这个抽象类将由具体的类Triangle,SquareCircle实现。

如何在Ruby哲学之后做到这一点?

+3

只需创建一个基类,不实例化。看起来对我来说足够了。 :) –

+0

记住Ruby是动态类型的,所以你甚至不需要基类 - 只有三个类都有'get_area'方法。 – matt

回答

2

定义一个正常的类AbstractFigure与方法get_area,只是提高NotImplementedError。然后每个派生类用它自己的实现覆盖get_area方法。

class AbstractFigure 
    def get_area 
     raise NotImplementedError.new('appropriate error message') 
    end 
end 

class Square < AbstractFigure 
    def get_area 
     # implementation here 
    end 
end 
5

你是正确的,不存在作为红宝石一个明确的概念,不像它的大量使用像Java语言编写的。

但是你也是对的,有很多情况需要保证。

下面是我已经走了一下,你的榜样 -

class AbstractShape 
    attr_accessor :edges 

    def initialize 
    # ... 
    end 

    def get_area 
    raise NoMethodError("Override this implementation") 
    end 
end 


class Square < AbstractShape 
    def initialize 
    # square-specific stuff 
    super 
    end 

    def get_area 
    self.edges * foo * bar 
    end 
end 

的关键是定义在顶层的可读性和一致性,所有可用的方法,但要确保他们提出如果有错误用过的。

如果有,你是绝对肯定会以同样的方式在所有的形状被一致地使用,那么一个方法把它定义在AbstractShape

attr_accessor也将继承,所以你必须@edges可在每每个形状的实例基础。但是您仍然可以在AbstractShape类中引用@edges,因为它们只会使用正确的本地实例变量。

0

使用Class::newModule#const_set

k = Class.new do 
     def area(width, height) 
     width*height 
     end 
    end 

["A", "B"].each { |sub| Object.const_set(sub, Class.new(superclass=k)) } 
    #=> ["A", "B"] 

class A 
    def perimeter(width, height) 
    2*(width+height) 
    end 
end 

A.superclass 
    #=> #<Class:0x007fd26a05d5b8> 
B.superclass 
    #=> #<Class:0x007fd26a05d5b8> 
A.instance_method(:area).owner 
    #=> #<Class:0x007fd26a05d5b8> 
A.new.area(3,4) 
    #=> 12 
A.new.perimeter(5,10) 
    #=> 30 
k.new.area(2,5) 
    #=> 10 
相关问题