我正在尝试使用Ruby实现基于货币的应用程序,我发现:
require 'dollar'
require 'franc'
puts 'Why does this not work?'
class Money
attr_reader :amount
def self.dollar(number)
Dollar.new number
end
def ==(other)
self.amount == other.amount
end
def self.franc(number)
Franc.new(number)
end
end
我有Franc
类看起来像这样:
require 'money'
class Franc < Money
attr_reader :amount
def initialize(amount)
@amount = number
end
def times(mul)
amount = @amount * mul
Franc.new(amount)
end
def ==(other)
return false unless other.is_a? self.class
super
end
end
这是将Kent Beck的一些代码直接翻译成Ruby。当我运行bin/rspec
时,我看到了:
/home/vamsi/Do/wycash/lib/franc.rb:3:in `<top (required)>': uninitialized constant Money (NameError)
from /home/vamsi/Do/wycash/lib/money.rb:2:in `require'
from /home/vamsi/Do/wycash/lib/money.rb:2:in `<top (required)>'
from /home/vamsi/Do/wycash/lib/dollar.rb:1:in `require'
from /home/vamsi/Do/wycash/lib/dollar.rb:1:in `<top (required)>'
from /home/vamsi/Do/wycash/spec/dollar_spec.rb:1:in `require'
from /home/vamsi/Do/wycash/spec/dollar_spec.rb:1:in `<top (required)>'
from /home/vamsi/Do/wycash/.bundle/ruby/2.3.0/gems/rspec-core-3.5.4/lib/rspec/core/configuration.rb:1435:in `load'
from /home/vamsi/Do/wycash/.bundle/ruby/2.3.0/gems/rspec-core-3.5.4/lib/rspec/core/configuration.rb:1435:in `block in load_spec_files'
from /home/vamsi/Do/wycash/.bundle/ruby/2.3.0/gems/rspec-core-3.5.4/lib/rspec/core/configuration.rb:1433:in `each'
from /home/vamsi/Do/wycash/.bundle/ruby/2.3.0/gems/rspec-core-3.5.4/lib/rspec/core/configuration.rb:1433:in `load_spec_files'
from /home/vamsi/Do/wycash/.bundle/ruby/2.3.0/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:100:in `setup'
from /home/vamsi/Do/wycash/.bundle/ruby/2.3.0/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:86:in `run'
from /home/vamsi/Do/wycash/.bundle/ruby/2.3.0/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:71:in `run'
from /home/vamsi/Do/wycash/.bundle/ruby/2.3.0/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:45:in `invoke'
from /home/vamsi/Do/wycash/.bundle/ruby/2.3.0/gems/rspec-core-3.5.4/exe/rspec:4:in `<top (required)>'
from bin/rspec:17:in `load'
from bin/rspec:17:in `<main>'
答案 0 :(得分:2)
当我意识到它会开始变得过于冗长时,我会将其添加为评论。
当你说你直接从Kent Beck的书中翻译时,我假设你指的是他的TDD by Example book(这是我能找到的唯一一本参考货币例子的书)。我实际上无法在那本书中找到一个例子,但是它指的是循环依赖,但是根据以前的Java和C ++经验,你通常试图通过实现一个接口来打破循环依赖 - 对于Ruby,你可能想要参考以下问题对这个问题有很好的答案:
话虽如此,我认为你的设计已被打破。您的Money类应该定义所有Money类型的通用行为和属性。它应该对法郎或美元等一无所知......法郎的具体行为应完全包含在法郎类中。使用单个类来处理所有货币或使用继承 - 两者都没有多大意义。
答案 1 :(得分:1)
在第一个脚本中定义Money之后,应该放置require 'franc'
。
当Ruby执行你的second_script时,将定义Money类。
编辑: 通知要求不是问题:
# a.rb
puts "A"
require_relative 'b'
# b.rb
puts "B"
require_relative 'a'
# ruby a.rb
A
B
A
用load './b.rb'
替换require_relative将导致无限循环和“堆栈级别太深”错误。
尽管如此,你应该用money.rb定义Money,franc.rb中的Franc,......并且不要在Money中添加任何有关Franc的内容。