Использовать `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, относящаяся к типу класса, нет такой вещи, которая быстрая