2013-08-04 2 views
2

Я разрабатываю классы для технического решения чертежей. Я должен работать с геометрическими примитивами. Пример:Молчаливое изменение класса? возможно ли это в Ruby

# all specifications are left, bottom and width, height 
class Circle 
         # +--- this is for my later question 
         # v 
    def initialize(x,y,w,h=w) # left, bottom and w=x+2*radius 
     ... 
    end 
end 
# the Ellipse needs 4 specifications (no rotation here) 
class Ellipse 
    def initialize(x,y,w,h) # left, bottom and w=2*a, h=2*b 
     ... 
    end 
end 

Если кто-то будет использовать что-то вроде

primitive=Cricle.new(10,10,20,30) # note different width and height 

было бы возможно вернуть Ellipse вместо (немного как: "либеральным в том, что вы принимаете ... Jon Принцип устойчивости Postel)?

Я думаю, что просто include Ellipse должен сделать трюк, так как кругом и Ellibse более или менее равны, я не стараюсь, но это изменило бы class.name, и что будет происходить (в Ruby), если я могу это сделать?

+1

Я не думаю, что это имеет смысл. Поскольку они отличаются только этими измерениями, я не верю, что есть необходимость в другом классе. Круг - это эллипс. – Ross

+0

@ Ross: да, это, вычисляя площадь круга, думая об этом как эллипс с a = b, стоит дорого, а использование «if» прерывает OO. Я думаю, что есть причина, почему даже в SVG есть и тег – halfbit

+0

OK, тогда наследование - это ответ! (например, ответ Джеффри ниже) – Ross

ответ

1
def Circle.new(x,y,w,h) 
    if w != h 
    Ellipse.new x,y,w,h 
    else 
    super 
    end 
end 
+0

Это очень короткий ответ, выглядит правильно для меня, поэтому я должен объяснить это сам: я переопределяю «новый» оператор класса Circle, возвращая эфир экземпляром Circle или экземпляром Ellipse ? – halfbit

+0

Em .. Вы должны получить больше информации о том, как работает Class.new. Прочтите книгу «Язык программирования Ruby» Дэвида Фланагана и Юкихиро Мацумото (создателя языка). –

+0

На ваш вопрос: да, выглядит так. Но серьезно, прочитайте книгу. =) P.S. Никогда не делайте те же самые трюки в реальном коде;) –

3

Да, вы можете (в пределах Circle класса просто добавить следующее):

def self.new(x, y, w, h) 
    return Ellipse.new(x, y, w, h) if w != h 
    super 
end 

Дело в том, что, да, так же как вы сказали, что это очень плохая практика. В этом случае вы можете организовать вещи немного лучше, и вы вообще никогда не должны кончать тем, что пишете такой хак. Вот пример:

class Ellipse 
    def initialize(x, y, w, h = w) 
     # (x, y) is the origin point 
     # w = width, h = height 
     # ... 
    end 
end 

class Circle < Ellipse 
    def initialize(x, y, d) 
     # (x, y) is the origin point 
     # d = diameter 
     # ... 
     super x, y, d, d 
    end 
end 

Фактически, круг является частным случаем эллипса. И делая это, вы разъясняете, специализируясь на конструкторе Ellipse в рамках метода Circle#initialize.

+0

sry, мой вопрос был для понимания Ruby, а не OO. В моем случае все методы «Круг» и «Эллипс» различны, подклассифицируя это, является акадмическим вопросом и не должен (IMHo) быть точкой этой задачи. Но спасибо (!) За ваш пример. Это делает мой вопрос более ясным: что, если я получу эллипс с h = w, я должен вернуть «круг», чтобы низкие расчеты. В этом случае этот плохой «взлом» начинает иметь смысл :-) - «вам нужно знать правила, чтобы сломать их правильно» лама. – halfbit

Смежные вопросы