2013-11-21 2 views
0
class Account 
    attr_accessor :balance 

    def initialize (amount=0) 
     self.balance = amount 
    end 

    def -(x) 
     self.balance -= x 
    end 

    def +(x) 
     self.balance += x 
    end 

    def to_s 
     puts "Balance is #{self.balance} !!!!!!!!!" 
    end 


end 

acc = Account.new(20) 
acc -=5 

Может кто-нибудь объяснить, почему это работает, чтобы написать: puts acc (рендеринг 15 в результате), но эта строка: puts acc.balance не работают (он говорит undefined method balance, однако это не метод, он должен следует рассматривать как свойство/атрибут) Заранее благодаренсо ссылкой атрибутов в Ruby,

+0

Какую цель здесь обслуживает 'attr_accessor'? Почему бы просто не использовать '@ balance'? – Max

ответ

2

Источник вашей ошибки является линией

acc -= 5 

это assings результата (возвращаемое значение) методы Substraction АССА переменным, и этот результат Fixnum экземпляра, который не имеет balance метод, определенный ,

Если вы хотите, чтобы ваши + и - метод для возврата Account экземпляра, вам необходимо указать следующее:

def +(x) 
    self.balance += x 
    self 
end 

т.д.

Кстати, в Ruby, методы доступ метода.

4

acc -= 5 эквивалентен acc = acc - 5.

acc - 5 является 15 (по Account#- методу); acc = acc - 5 - это как acc = 15.

Сейчас acc является объектом Fixnum.


Как насчет реализации +, - как следовать?

def -(x) 
    Account.new(self.balance - x) 
end 

def +(x) 
    Account.new(self.balance + x) 
end 
+0

Я понимаю, что метод «-» используется для вывода денег из баланса текущего счета, поэтому не был удивлен результатом 15. Но все же не понимаю, почему «puts acc.balance» не работает. Разве «баланс» не является «атрибутом» каждого «экземпляра»? Возможно, мой синтаксис неверен. Спасибо. – Sam

+0

@Sam. В соответствии с вашим кодом возвращаемое значение '' '' '' '' '' 'Fixnum', а не экземпляр' Balance'. – falsetru

+0

@Sam, я добавил альтернативную реализацию '-',' + '; которые возвращают новый экземпляр 'Account' вместо' Fixnum'. – falsetru

1

Вы хотите редактировать свои два способа сделать += и -= работу, так что они возвращают объект на месте:

def -(x) 
    self.balance -= x 
    self 
end 

def +(x) 
    self.balance += x 
    self 
end 

Таким образом, объект он переназначен к себе.

1

Упс, есть много ошибок, которые были связаны с этим. Я не могу объяснить все проблемы, но давайте посмотрим, как далеко я могу получить:

Прежде всего вы переопределил #+ и #- методы, чтобы дать им семантику вы ожидаете от #+= и #-=. Учитывая это: если вы используете acc-5 в своем примере (вместо acc-=5), поведение близко к ожидаемому, irb отобразит 15, так как это результат вашего метода #- (который имеет побочный эффект вычитания 5 баланса, а также).

Однако, как вы называете #-= в вашем примере интерпретатор рубина заканчивает назначая методы приводят Fixnum15 к вашим acc -переменным. Это даст вам сообщение об ошибке NoMethodError: undefined method 'balance' for 15:Fixnum при попытке получить доступ к #balance, который определен для вашего класса Account.

Ваш метод #- должен возвращать Account -объект, не изменять существующее состояние объекта и возвращать результат как Fixnum. См. http://ruby.about.com/od/oo/ss/Overloading-Operators.htm для примеров переопределения операторов. Я понимаю, что это как-то поражает вашу цель, как вам хотелось бы использовать #-=, чтобы изменить объект на месте, но он работает только при создании другого Account -instance в Ruby, поскольку вы не можете переопределить #-= напрямую (см. Ссылку выше) ,

Конечно, вы можете задать #withdraw-метод, чтобы получить семантику, которую вы желаете.

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