【问题标题】:How can I call a function with a dictionary?如何使用字典调用函数?
【发布时间】:2018-09-18 16:03:51
【问题描述】:

我尝试创建一个Dictionary 来调用一些函数。

我的数组接受一个键 Int、一个字符串和一个函数,如下所示:

let list_weapons: [Int: [Any]]  = [1: ["Sword", attack_sword],
                                   2: ["Magic wand", heal_magic_wand],
                                   3: ["Hammer", attack_hammer],
                                   4: ["Axe", attack_axe]]

这些函数将Class 作为参数,如下所示:

func attack_sword(character: Character)

我尝试这样调用我的函数,但它不起作用。

list_weapons[1]![1](character: Character) 

不能调用非函数类型'Any'的值

如果你有一些想法或用另一个容器给我建议

谢谢

【问题讨论】:

    标签: arrays swift function dictionary


    【解决方案1】:

    您无需将方法存储在字典中即可解决您的问题。在我看来,架构解决方案在这里会更好。如果你愿意,你可以使用选择器,但我想如果你只是这样做,事情会容易得多

    // Here you can specify all common thing about your weapons
    protocol Weapon: class {
        var name: String { get }
        func attack(character: Character)
    }
    
    // Each weapon has its own class which can contain eveything you need
    class Sword: Weapon { }
    class MagicWand: Weapon { }
    class Hammer: Weapon { }
    class Axe: Weapon { }
    
    // That's how you can store you weapons list
    // You can use a dictionary if you like
    let weaponsArray: [Weapon]  = [Sword(),
                                   MagicWand(),
                                   Hammer(),
                                   Axe()]
    
    // And that's how you can use them
    weaponsArray[0].attack(character: character)
    

    【讨论】:

    • “您不能在数组中存储方法。” - 当然可以。
    【解决方案2】:

    使用Any 的数组来存储字符串和具有特定签名的闭包(函数)是一个糟糕的选择。最好声明一个具有两个正确类型属性的struct。然后将这些结构存储在您的字典中。

    struct Action {
        let name: String
        let function: (Character) -> ()
    }
    
    let list_weapons: [Int: Action] = [
        1: Action(name: "Sword", function: attack_sword),
        // and the rest
    ]
    
    list_weapons[1]!.function(someCharacter)
    

    【讨论】:

      【解决方案3】:

      你必须castAnyFunction才能使用它。

      let f = (list_weapons[1]![1] as! (Character) -> Void)
      f("a") //it will invoke attack_sword("a")
      

      并且没有临时变量,

      (list_weapons[1]![1] as! (Character) -> Void)("a")
      

      【讨论】:

        【解决方案4】:

        您可以将元素转换为函数类型:

        if let attack = list_weapons[1]![1] as? ((Character) -> Void) {
            attack(...)
        } else {
            print("Cannot attack")
        }
        

        但你最好重新设计你的数据模型。使用字典会很快变得混乱。这是一种方法:

        protocol Weapon {
            var name: String { get }
            func attack(character: Character)
        }
        
        struct Sword: Weapon {
            let name = "Sword"
            func attack(character: Character) { ... }
        }
        
        struct MagicWand: Weapon {
            let name = "Magic Wand"
            func attack(character: Character) { ... }
        }
        
        struct Hammer: Weapon {
            let name = "Hammer"
            func attack(character: Character) { ... }
        }
        
        struct Axe: Weapon {
            let name = "Axe"
            func attack(character: Character) { ... }
        }
        
        let weapons: [Weapon] = [Sword(), MagicWand(), Hammer(), Axe()]
        weapons[1].attack(character: ...)
        

        您可以使用不同的伤害、独特的功能、等级等来扩展每种武器。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-10-28
          • 2023-03-14
          • 2017-06-03
          • 2020-03-12
          • 2017-04-14
          • 2019-11-02
          相关资源
          最近更新 更多