什么是最简单,最像Ruby的方式让一个构造函数返回一个合适类型的对象?
更具体地说,这是一个虚拟的例子:说我有两个类Bike和Car哪个子类Vehicle.我要这个:
Vehicle.new('mountain bike') # returns Bike.new('mountain bike')
Vehicle.new('ferrari') # returns Car.new('ferrari')
Run Code Online (Sandbox Code Playgroud)
我已经在下面提出了一个解决方案,但它的使用allocate似乎太过实现了.有什么其他方法,或者我的确实可以吗?
Dig*_*oss 20
如果我制作一个未被称为1 的工厂方法,new或者initialize我认为这并没有真正回答"我如何制作一个......构造函数......"的问题,但我认为这就是我要做的...
class Vehicle
def Vehicle.factory vt
{ :Bike => Bike, :Car => Car }[vt].new
end
end
class Bike < Vehicle
end
class Car < Vehicle
end
Run Code Online (Sandbox Code Playgroud)
c = Vehicle.factory :Car
c.class.factory :Bike
Run Code Online (Sandbox Code Playgroud)
1.调用方法工厂在这个教学示例中非常有效但是IRL你可能想在评论中考虑@AlexChaffee的建议.
cla*_*cke 17
我今天这样做了.翻译成车辆,它看起来像这样:
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
Run Code Online (Sandbox Code Playgroud)
我喜欢类的标签与类本身一起保存,而不是有关于存储在超类中的子类的信息.没有调用构造函数new,但我认为使用该特定名称没有任何好处,这会使事情变得棘手.
> Vehicle.vehicle_from_name 'ferrari'
=> #<Car:0x7f5780840448>
> Vehicle.vehicle_from_name 'mountain bike'
=> #<Bike:0x7f5780839198>
Run Code Online (Sandbox Code Playgroud)
请注意,某些东西需要确保在运行vehicle_from_name之前加载这些子类(可能这三个类将位于不同的源文件中),否则超类将无法知道哪些子类存在,即您不能依赖自动加载来拉取这些子类运行构造函数时的类.
我通过将所有子类放在例如vehicles子目录中并将其添加到以下结尾来解决这个问题vehicle.rb:
require 'require_all'
require_rel 'vehicles'
Run Code Online (Sandbox Code Playgroud)
使用require_allgem(可在https://rubygems.org/gems/require_all和https://github.com/jarmo/require_all找到)
改编自这里,我有
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
Run Code Online (Sandbox Code Playgroud)