【问题标题】:How do I make a function that takes any function that's defined in a Protocol as its parameter?如何制作一个将协议中定义的任何函数作为其参数的函数?
【发布时间】:2015-12-16 05:58:22
【问题描述】:

我正在开发一款纸牌游戏,并希望创建一个函数来循环遍历我的 Players 数组并为每个玩家执行一些功能,所以我没有大量

for var player in Players {
    player.doSomeFunction()
}

遍布我的代码。相反,我想要如下内容:

func everyone(doThis: func) {
    for var player in Players {
        player.doThis(<params, etc…>)
    }
}

这样我就可以在代码的其他地方调用Players.everyone(doThis(params, etc…)),而不必每次我需要让所有玩家做某事时都循环播放器。

如何创建一个函数,将协议中定义的任何函数作为其参数? 我遇到的问题是,当你在 Swift 中使用函数作为参数时,你必须在函数声明中定义函数参数的参数和返回类型。或者,是否有调用Players.forAllElements(doThisFunction) 的内置方法(其中PlayersArray&lt;Player&gt;)?

如果有帮助,我有两个符合 Player 协议的类:ComputerPlayerHumanPlayer

【问题讨论】:

  • players.forEach { $0.doSomeThing(parameter, ...) } 呢?
  • Mini-markdown 限制了我的风格:不能使用多行代码示例。当我尝试Players.forEach { $0.sortHand() } 时,它抱怨不可变性。使用in this post 建议的方法会更好吗?

标签: arrays swift function swift2 function-parameter


【解决方案1】:

似乎没有办法用 swift 表示 any-function-in-a-protocol,以用于某种参数类型的定义。

但是,使用 currying 和函数类型,您可以执行类似的操作:.您可以针对具有相同签名的所有函数:

class Player {
    var name: String
    init(_ name: String) {
        self.name = name
    }

    // Both actions, even if they have different parameter names,
    // have the same function signature
    func actionOne(foo: String, count:Int) {
        print("actionOne:\(name):\(foo):\(count)")
    }

    func actionTwo(bar: String, amount: Int) {
        print("actionTwo:\(name):\(bar):\(amount)")
    }
}

let players = [Player("Primero"), Player("Segundo")]

// A function type that receives a Player object, and returns a
// function with the `String, Int` signature
typealias PlayerActionType = (Player) -> (String, Int) -> ()

// This is the function that takes the curried function, and can
// run any function sharing the same signature
func performAction(curriedFunction: PlayerActionType) {
    for currentPlayer in players {
        let actionFunction = curriedFunction(currentPlayer)
        actionFunction("string", 3)
    }
}

performAction(Player.actionOne)
performAction(Player.actionTwo)

// Prints:
// actionOne:Primero:string:3
// actionOne:Segundo:string:3
// actionTwo:Primero:string:3
// actionTwo:Segundo:string:3

【讨论】:

  • 等我回到我的电脑前我会调查一下,但我已经喜欢你选择的玩家名字了。
【解决方案2】:

你可以这样做。 makePrint 是采用选择器的函数。你可以这样称呼它。

 [self makePrint:@selector(print)];

-(void)makePrint:(SEL)selector{
    [self performSelector:selector];
}
-(void)print{
   NSLog(@"print");
 }

【讨论】:

  • 这看起来不是很 Swifty :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-03
  • 2019-03-19
  • 2019-03-11
  • 1970-01-01
  • 1970-01-01
  • 2020-10-31
相关资源
最近更新 更多