让单个构造函数返回适当类型的对象的最巧妙、最类似Ruby的方式是什么?
更具体地说,这里有一个虚拟示例:假设我有两个类Bike
和Car
,它们是Vehicle
的子类。我想要的是:
Vehicle.new('mountain bike') # returns Bike.new('mountain bike')
Vehicle.new('ferrari') # returns Car.new('ferrari')
我在下面提出了一个解决方案,但它使用了allocate
,这似乎太重实现了。其他的方法是什么,或者我的方法真的可以吗?
发布于 2011-06-09 23:50:13
这是我今天做的。翻译成车辆,它看起来像这样:
class Vehicle
VEHICLES = {}
def self.register_vehicle name
VEHICLES[name] = self
end
def self.vehicle_from_name name
VEHICLES[name].new
end
end
class Bike < Vehicle
register_vehicle 'mountain bike'
end
class Car < Vehicle
register_vehicle 'ferrari'
end
我喜欢类的标签与类本身一起保存,而不是将有关子类的信息与超类一起存储。这个构造函数不叫new
,但我看不出使用这个名称有什么好处,而且它会使事情变得更加棘手。
> Vehicle.vehicle_from_name 'ferrari'
=> #<Car:0x7f5780840448>
> Vehicle.vehicle_from_name 'mountain bike'
=> #<Bike:0x7f5780839198>
请注意,需要确保在运行vehicle_from_name之前加载这些子类(假设这三个类位于不同的源文件中),否则超类将无法知道存在哪些子类,即您不能在运行构造函数时依赖于自动加载来拉入这些类。
我解决这个问题的方法是将所有的子类都放在一个vehicles
子目录中,并在vehicle.rb
的末尾添加以下内容
require 'require_all'
require_rel 'vehicles'
使用require_all
gem (可在https://rubygems.org/gems/require_all和https://github.com/jarmo/require_all找到)
发布于 2009-10-04 04:18:32
改编自here,我有
class Vehicle
def self.new(model_name)
if model_name == 'mountain bike' # etc.
object = Bike.allocate
else
object = Car.allocate
end
object.send :initialize, model_name
object
end
end
class Bike < Vehicle
def initialize(model_name)
end
end
class Car < Vehicle
def initialize(model_name)
end
end
发布于 2009-10-04 14:11:08
如果是包含模块而不是超类呢?这样,您仍然可以让#kind_of?
正常工作,并且没有默认的new
。
module Vehicle
def self.new(name)
when 'mountain bike'
Bike.new(name)
when 'Ferrari'
Car.new(name)
...
end
end
end
class Bike
include Vehicle
end
class Car
include Vehicle
end
https://stackoverflow.com/questions/1515577
复制相似问题