crystal lang:如果将Class作为字段

时间:2018-08-10 07:02:15

标签: crystal-lang

我只是写一个异常,该异常应存储一个Class对象作为错误消息过程的字段。

class BadType < Exception
    getter should_be : Class
    getter actual : Class
end
def feed(pet : Animal, food : Food)
    raise BadType.new should_be: Cat, actual: pet.class if food == "fish" && !pet.is_a?(Cat)
end

但是,Class是抽象的,因此不能在此处用作字段类型。

那么,如何解决我的情况呢?我没有找到Class的任何派生类,是否就意味着永远不能将Class对象存储为字段?但是这里我的问题是对此的有意义的用法(任何取决于输入的类型检查都可能需要此BadType)。

我不确定是否错过了什么,所以我先来了这里。

2 个答案:

答案 0 :(得分:4)

Class尚不能用作ivar类型。也许永远不会,我不知道。

但是实际上您可以将泛型用于具体的数据类型,从参数向构造函数推断:

# possible workaround
class Foo(T, U)
  def initialize(@bar : T, @baz : U)
  end
end

Foo.new String, Int32

我不知道您的确切用例,但是可能您实际上并不需要这些值作为类。无论如何,您可能无法做很多事情,并且从您的示例中提取信息,我想这主要是为了显示调试信息。

因此很可能仅存储类的名称(作为字符串)将是解决此问题的更好方法。

# better solution
class Foo
  @bar : String
  @baz : String
  def initialize(bar : Class, baz : Class)
    @bar = bar.name
    @baz = baz.name
  end
end

Foo.new String, Int3

泛型参数意味着为Foo使用的每个类组合创建一个新的具体类型。这可能会影响编译器的性能。

我绝对会为此使用字符串。即使以后需要类来进行某些特殊处理,也最好使用宏生成的查找表将字符串映射到常量。

答案 1 :(得分:3)

尝试generics

class BadType(ClassA, ClassB) < Exception
  getter should_be : ClassA
  getter actual : ClassB

  def initialize(@should_be, @actual)
    @message = "Bad type: should be #{@should_be}, actual is #{@actual}"
  end
end

def feed(pet : Animal, food : Food)
  raise BadType(Animal.class, Animal.class).new should_be: Cat, actual: pet.class if food == "fish" && !pet.is_a?(Cat)
end

class Animal
end

record Food, food : String do
  def ==(other_food)
    @food == other_food
  end
end

class Cat < Animal
end

class Dog < Animal
end

feed pet: Dog.new, food: Food.new("fish")

输出:

Unhandled exception: Bad type: should be Cat, actual is Dog (BadType(Animal:Class, Animal:Class))
  from /eval:11:3 in 'feed'
  from /eval:29:1 in '__crystal_main'
  from /usr/lib/crystal/crystal/main.cr:104:5 in 'main_user_code'
  from /usr/lib/crystal/crystal/main.cr:93:7 in 'main'
  from /usr/lib/crystal/crystal/main.cr:133:3 in 'main'
  from __libc_start_main
  from _start
  from ???

演示:https://carc.in/#/r/4pgs