Использовать `self` в качестве параметра по умолчанию
Можно ли использовать self
в качестве параметра по умолчанию в Swift? Этот код выглядит довольно прямолинейно, но я не понимаю сообщения, которое компилятор отбрасывает:
func printTree(node: TreeNode = self, tabs: String = "") {
println(tabs + node.name!)
node.children.forEach { printTree(node: $0, tabs: tabs+"\t") }
}
Ошибка:
'TreeNode -> () -> TreeNode' is not convertible to 'TreeNode'
А?
Есть, вероятно, другие способы, с помощью которых я мог бы решить обход дерева, но на самом деле мне просто интересно установить ограничение по умолчанию. Это настоящая вещь? Есть ли упоминание об этом в документах? Я не мог найти его.
Update:
Я сделал это с нуля без каких-либо зависимостей (у меня была иерархия класса и пользовательский патч forEach
, который использовался ранее). Это все еще ошибки:
class PeanutButterJelly {
var children: [PeanutButterJelly]?
func doDance(){ println("dancing") }
func everybodyDanceNow(pbj: PeanutButterJelly = self) {
pbj.doDance()
if let children = pbj.children {
for child in children { child.doDance() }
}
}
}
Ошибка:
Swift compilation error: unresolved identifier 'self'
Xcode 6.3.2
Ответы
Ответ 1
Можно ли использовать self в качестве параметра по умолчанию в Swift
Нет. Это по той же причине, что вы не можете сказать self
при инициализации метода экземпляра:
class TreeNode {
var otherNode : TreeNode = self // Use of unresolved identifier `self`
func printTree(tree:TreeNode = self) { } // Use of unresolved identifier `self`
}
В то время, когда вы определяете этот объект (свойство или метод), нет такой вещи, как self
. Будет <<20 > позже, когда этот метод вызывается, внутри тела функции - потому что функция будет вызываться в некотором экземпляре, а именно self
.
Один простой способ сделать то, что вы хотите сделать, - сделать этот параметр необязательным с значением nil
по умолчанию. Затем в теле функции проверьте nil
и используйте self
:
class TreeNode {
func printTree(tree:TreeNode? = nil) {
let treeToPrint = tree ?? self
// do stuff
}
}
Теперь законно называть printTree
без параметра, и он делает то, что вы хотите:
TreeNode().printTree()
Ответ 2
Причина, по которой unresolved identifier 'self'
- это область одного неявного свойства экземпляра self
', находится внутри каждого метода экземпляра. Если вы измените значение по умолчанию от self к детям в вашем примере, вы увидите сообщение об ошибке
'PeanutButterJelly.Type' не имеет члена с именем 'children'
В отличие от objc существует другая версия self, относящаяся к типу класса, нет такой вещи, которая быстрая