我想创建一个抽象类,它将根据初始化参数创建具体实例。例如:
class SomethingGeneric
def self.new(type, arg)
class_name = "#{type.capitalize}Something"
if obj.const_defined?(class_name)
a_class = obj.const_get(class_name)
else
raise ArgumentError, "Concrete something '#{type}' was not found"
end
obj = a_class.new(arg)
return obj
end
end # class
然后我想拥有FooSomething< SomethingGeneric,BarSomething< SomethingGeneric等等。然后当我这样做时:
obj = SomethingGeneric.new("foo", arg)
我会得到FooSomething实例。
我的问题是“新”方法。我已经定义了SomethingGeneric.new,但是FooSomething和BarSomething是SomethingGeneric的子类,因此它们继承了在这里使用错误参数调用的“new”方法:
obj = a_class.new(arg)
其中一个解决方案是为工厂方法'new'使用另一个名称。但是我想坚持方便并保留名为'new'的抽象超类工厂方法。
解决此问题最简洁的正确方法是什么?
答案 0 :(得分:3)
你的新方法应该采用一个参数:* args
你想要从数组中取出第一个项目作为你的类型var,然后从数组中删除该项目,这样你就可以将其余的args传递给下一个新的调用。
数组#shift将为您提供第一项,然后将其删除。
class SomethingGeneric
def self.new(*args)
type = args.shift
class_name = "#{type.capitalize}Something"
if obj.const_defined?(class_name)
a_class = obj.const_get(class_name)
else
raise ArgumentError, "Concrete something '#{type}' was not found"
end
obj = a_class.new(*args)
return obj
end
end # class
答案 1 :(得分:0)
真正的问题是你需要这种行为?看起来你来自像Java这样的语言,其中工厂等是常态。您是否需要此行为以便您知道该对象将响应您将要使用的特定方法?使用界面怎么样?
类似的东西:
class GenericThing
def name # Interface method
# Return a String of the name of the GenericThing.
end
end
class GenericSomething
def name
# ...
end
end
class Whatever
def self.method_that_uses_the_generic_interface(generic)
if generic.respond_to?(:name) # Check for interface compliance
generic.name
else
raise "Generic must implement the name method."
end
end
end
如果您真的想使用Abstract类,可以执行以下操作:
class AbstractGeneric
def name
raise "You must override name in subclasses!"
end
class GenericThing < AbstractGeneric
def name
"GenericThing"
end
end
class GenericSomething < AbstractGeneric
# ...
end
class Whatever
def self.method_that_uses_the_generic_interface(generic)
if generic.kind_of? AbstractGeneric
generic.name
# Will raise if the interface method hasn't been overridden in subclass.
else
raise "Must be a instance of a subclass of AbstractGeneric!"
end
end
end
在这种情况下,行为将是这样的:
generic_thing = GenericThing.new
Whatever.method_that_uses_the_generic_interface(generic_thing)
=> "GenericThing"
generic_something = GenericSomething.new
Whatever.method_that_uses_the_generic_interface(generic_something)
# Will raise "You must override name in subclass!"
object = Object.new
Whatever.method_that_uses_the_generic_interface(object)
# Will raise "Must be an instance of a subclass of AbstractGeneric!"