如何将类型限制为接口的 class 而不是该接口的实例?
How to limit a type to the class of a interface and not the instance of that interface?
给定模块中的以下接口:
module Action
abstract def perform
end
我想用它来实例化实现它的不同 classes:
class Run
include Action
def perform
puts "run!"
end
end
class Jump
include Action
def perform
puts "jump!"
end
end
我知道可以定义像 [] of Action
这样的数组并能够存储 Action
的实例,但我对 classes 而不是实例感兴趣。
我想知道如何定义类型限制,以便我可以存储对实现接口的 class 的引用,而不是特定实例。
我的 objective 能够实例化某些 class 的新实例并能够调用其中的 perform
方法。
此时可以编写如下代码:
actions = [Run, Jump]
actions.each do |klass|
instance = klass.new.as(Action)
instance.perform
end
事情会起作用,但是不可能将 classes 的列表存储到实例变量中,因为类型限制有点严格。
这种情况下的类型限制语法是什么?
想到的第一个想法是使用 [] of Action.class
,但这行不通。也许这应该可行,但它需要在编译器中使用 change/enhancement。
在此期间您可以这样做:
module Action
abstract def perform
end
class Run
include Action
def perform
puts "run!"
end
end
class Jump
include Action
def perform
puts "jump!"
end
end
module ActionFactory
abstract def new : Action
end
struct GenericActionFactory(T)
include ActionFactory
def new
T.new
end
end
ary = [] of ActionFactory
ary << GenericActionFactory(Run).new
ary << GenericActionFactory(Jump).new
action = ary[0].new
p action
action = ary[1].new
p action
@asterite 提出的工厂建议的另一种方法是使用模块 extend
它在 class 上,但也用它来定义实例变量的类型:
module Action
module Interface
end
macro included
extend Interface
end
abstract def perform
end
class Run
include Action
def perform
puts "run!"
end
end
class Jump
include Action
def perform
puts "jump!"
end
end
list = [] of Action::Interface
list << Run
list << Jump
list.each do |klass|
instance = klass.new
instance.perform
end
这让我也可以使用 Action.class
作为类型要求,因此只能使用实现 Action
的 classes 并且使用 Action::Interface
无需执行任何对从数组中获得的元素进行转换:
class Worker
@actions = [] of Action::Interface
def add(action : Action.class)
@actions << action
end
def perform
@actions.each do |klass|
instance = klass.new
instance.perform
end
end
end
a = Worker.new
a.add Run
a.add Jump
a.add Jump
a.perform
给定模块中的以下接口:
module Action
abstract def perform
end
我想用它来实例化实现它的不同 classes:
class Run
include Action
def perform
puts "run!"
end
end
class Jump
include Action
def perform
puts "jump!"
end
end
我知道可以定义像 [] of Action
这样的数组并能够存储 Action
的实例,但我对 classes 而不是实例感兴趣。
我想知道如何定义类型限制,以便我可以存储对实现接口的 class 的引用,而不是特定实例。
我的 objective 能够实例化某些 class 的新实例并能够调用其中的 perform
方法。
此时可以编写如下代码:
actions = [Run, Jump]
actions.each do |klass|
instance = klass.new.as(Action)
instance.perform
end
事情会起作用,但是不可能将 classes 的列表存储到实例变量中,因为类型限制有点严格。
这种情况下的类型限制语法是什么?
想到的第一个想法是使用 [] of Action.class
,但这行不通。也许这应该可行,但它需要在编译器中使用 change/enhancement。
在此期间您可以这样做:
module Action
abstract def perform
end
class Run
include Action
def perform
puts "run!"
end
end
class Jump
include Action
def perform
puts "jump!"
end
end
module ActionFactory
abstract def new : Action
end
struct GenericActionFactory(T)
include ActionFactory
def new
T.new
end
end
ary = [] of ActionFactory
ary << GenericActionFactory(Run).new
ary << GenericActionFactory(Jump).new
action = ary[0].new
p action
action = ary[1].new
p action
@asterite 提出的工厂建议的另一种方法是使用模块 extend
它在 class 上,但也用它来定义实例变量的类型:
module Action
module Interface
end
macro included
extend Interface
end
abstract def perform
end
class Run
include Action
def perform
puts "run!"
end
end
class Jump
include Action
def perform
puts "jump!"
end
end
list = [] of Action::Interface
list << Run
list << Jump
list.each do |klass|
instance = klass.new
instance.perform
end
这让我也可以使用 Action.class
作为类型要求,因此只能使用实现 Action
的 classes 并且使用 Action::Interface
无需执行任何对从数组中获得的元素进行转换:
class Worker
@actions = [] of Action::Interface
def add(action : Action.class)
@actions << action
end
def perform
@actions.each do |klass|
instance = klass.new
instance.perform
end
end
end
a = Worker.new
a.add Run
a.add Jump
a.add Jump
a.perform