【问题标题】:crystal lang : in case of a Class as a fieldcrystal lang :如果将 Class 作为字段
【发布时间】:2018-08-10 07:02:14
【问题描述】:

我只是在写一个异常,它应该存储一个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)。

不知道是不是错过了什么,所以先来了。

【问题讨论】:

    标签: crystal-lang


    【解决方案1】:

    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 使用的每个类组合创建一个新的具体类型。这可能会对编译器性能产生影响。

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

    【讨论】:

      【解决方案2】:

      试试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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多