如何制作一个函数,将协议中定义的任何函数作为其参数?

How do I make a function that takes any function that's defined in a Protocol as its parameter?

我正在开发一款纸牌游戏,我想制作一个函数来循环我的 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中的参数,你必须在函数声明中定义函数参数的参数和return类型。或者,是否有内置方法调用 Players.forAllElements(doThisFunction)(其中 PlayersArray<Player>)?

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

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

 [self makePrint:@selector(print)];

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

any-function-in-a-protocol in swift 似乎无法表达,以用于某种参数类型的定义.

但是,使用 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