2017-09-07 6 views
3

Ich versuche, einen Initialisierer für eine Klasse zu erstellen, die einen Hash als Parameter erhält. Der Hash ist ein {String => Type} Hash und kann verschachtelt werden. Ich erhalte eine Fehlermeldung, wenn Sie diesen Code ausführen:Geben Sie Alias ​​und Hash als Methodenparameter ein

#file: types.cr 
class Types 
    alias Type = Nil | 
       Bool | 
       Int32 | 
       Int64 | 
       Float64 | 
       String | 
       Array(Type) | 
       Hash(String, Type) 

    def initialize(@input : Type) 
    end 
end 

input = {"a" => {"b" => {"c" => {"c1" => 1, "c2" => 2, "c3" => true}}}} 
s = Types.new(input) 

Hier ist der Fehler, den ich bekommen, wenn Sie den angezeigten Code ausgeführt wird:

$ crystal types.cr 

Error in types.cr:16: instantiating 'Types:Class#new(Hash(String, Hash(String, Hash(String, Hash(String, Bool | Int32)))))' 

s = Types.new(input) 
      ^~~ 

in types.cr:11: instance variable '@input' of Types must be Types::Type, not Hash(String, Hash(String, Hash(String, Hash(String, Bool | Int32)))) 

    def initialize(@input : Type) 
       ^~~~~~ 

Ist dies möglich mit Crystal? Wie soll ich das angehen?

Danke!

Antwort

4

Sie können diese Spezifizierungs Typ jeder Hash tun:

c = {"c1" => 1, "c2" => 2, "c3" => true} of String => Types::Type 
b = {"c" => c} of String => Types::Type 
a = {"b" => b} of String => Types::Type 

t = Types.new({"a" => a} of String => Types::Type) 
pp t # => #<Types:0x103085ec0 
    # @input= 
    #  {"a" => {"b" => {"c" => {"c1" => 1, "c2" => 2, "c3" => true}}}}> 

Ein anderer Ansatz zu definieren und verwenden Hash-like type:

alias Type = Nil   | 
      Bool  | 
      Int32  | 
      Int64  | 
      Float64  | 
      String  | 
      Array(Type) | 
      Hash(String, Type) 

alias TypesHash = Hash(String, Type) 

t = TypesHash{ 
    "a" => TypesHash{ 
    "b" => TypesHash{ 
     "c" => TypesHash{ 
     "c1" => 1, "c2" => 2, "c3" => true, 
     }, 
    }, 
    }, 
} 

t           # {"a" => {"b" => {"c" => {"c1" => 1, "c2" => 2, "c3" => true}}}} 
t["a"]          # {"b" => {"c" => {"c1" => 1, "c2" => 2, "c3" => true}}} 
t["a"].as(TypesHash)["b"]     # {"c" => {"c1" => 1, "c2" => 2, "c3" => true}} 
t["a"].as(TypesHash)["b"].as(TypesHash)["c"] # {"c1" => 1, "c2" => 2, "c3" => true} 

So können Sie es an den Konstruktor wie TypesHash Objekt:

class Types 
    def initialize(@input : TypesHash); end 
end 

Types.new t 
Verwandte Themen