Несколько функций с тем же именем

Я новичок в Swift, и я проходил через несколько учебников, и многие из них определяют функцию более одного раза с тем же именем.

Я привык к другим языкам программирования, где это невозможно сделать, иначе он выдает ошибку.

Поэтому я проверил официальный Swift Manual и также проверил переопределить, чтобы узнать, что я могу извлечь из него, но все же я не могу понять следующий код:

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 10
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "MyTestCell")

    cell.textLabel?.text = "Row #\(indexPath.row)"
    cell.detailTextLabel?.text = "Subtitle #\(indexPath.row)"

    return cell
}

Из того, что я вижу, функция tableView устанавливается в строке # 1, а также в строке # 5, единственное отличие, которое я заметил, это то, что первая функция tableView возвращает Int, а вторая возвращает Object (UITableViewCell).

В этом случае я вижу, что в результате вторая функция НЕ переопределяет первый.

Что это значит и почему можно определить функцию более одного раза с тем же именем без переопределения?

Ответы

Ответ 1

Вам разрешено определять две функции с тем же именем, если они имеют разные типы, или если их можно различить по их внешним меткам аргументов параметра. Тип функции состоит из параметра Типы в круглых скобках, за которым следует ->, за которым следует возвращаемый тип. Обратите внимание, что метки аргументов НЕ являются частью функции Type. (Но см. UPDATE ниже.)

Например, следующие функции имеют одинаковое имя и имеют тип (Int, Int) -> Int:

// This:
func add(a: Int, b: Int) -> Int {
    return a + b
}

// Is the same Type as this:
func add(x: Int, y: Int) -> Int {
    return x + y
}

Это приведет к ошибке времени компиляции - изменение меток от a:b: до x:y: не отличает две функции. (Но см. UPDATE ниже.)

Использование функций г-на Веб в качестве примеров:

// Function A: This function has the Type (UITableView, Int) -> Int
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { ... }

// Function B: This function has the Type (UITableView, NSIndexPath) -> UITableViewCell
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { ... }

// Function C: This made up function will produce a compile-time error because
// it has the same name and Type as Function A, (UITableView, Int) -> Int:
func tableView(arg1: UITableView, arg2: Int) -> Int { ... }

Функция A и функция B выше не конфликтуют, потому что они имеют разные типы. Функция A и функция C выше конфликтуют, потому что они имеют один и тот же тип. Изменение меток параметров не разрешает конфликт, если типы остаются неизменными. (См. UPDATE ниже.)

override - совсем другое понятие, и я думаю, что некоторые из других ответов охватывают его, поэтому я пропущу его.

ОБНОВЛЕНИЕ: Некоторые из того, что я написал выше, неверны. Верно, что метки параметров функций не являются частью этого определения типа, но их можно использовать для различения двух функций, имеющих один и тот же тип, если у функции есть внешние метки, которые различны, так что компилятор может определить, какие которую вы пытаетесь вызвать, когда вы его вызываете. Пример:

func add(a: Int, to b: Int) -> Int {    // called with add(1, to: 3)
    println("This is in the first function defintion.")
    return a + b
}

func add(a: Int, and b: Int) -> Int {   // called with add(1, and: 3)
    println("This is in the second function definition")
    return a + b
}

let answer1 = add(1, to: 3)    // prints "This is in the first function definition"
let answer2 = add(1, and: 3)   // prints "This is in the second function definition"

Таким образом, использование внешних меток в определении функции позволит компилировать функции с тем же именем и того же типа. Таким образом, кажется, что вы можете писать несколько функций с тем же именем, если компилятор может различать их по их типам или по своим ярлыкам подписи. Я не думаю, что внутренние этикетки имеют значение. (Но я надеюсь, что кто-то меня исправит, если я ошибаюсь.)

Ответ 2

Вы думаете о перегрузке функций.

Выдержка из документации Apple здесь:

Вы можете перегрузить универсальную функцию или инициализатор, предоставив различные ограничения, требования или оба в параметрах типа в предложении универсального параметра. Когда вы вызываете перегруженную обобщенную функцию или инициализатор, компилятор использует эти ограничения, чтобы определить, какую перегруженную функцию или инициализатор вызывать.

Например:

protocol A { }
protocol B { }

class A1: A { }
class A2: A { }

class B1: B { }
class B2: B { }

func process<T: A>(value: T)
{
    // process values conforming to protocol A
}

func process<T: B>(value: T)
{
    // process values conforming to protocol B
}

или же:

func process(value: Int)
{
    // process integer value
}

func process(value: Float)
{
    // process float value
}

Эта путаница часто встречается, особенно если вы впервые переходите с Objective-C на Swift. Вы должны прочитать об именах параметров здесь.

Ответ 3

В Swift, как и в Objective-C, параметры функции составляют часть определения. Существует не две функции, называемые tableView, одна функция называется tableView(tableView:, numberOfRowsInSection:), а одна называется tableView(tableView:, cellForRowAtIndexPath:)

Ответ 4

Функции не совпадают, они разные. Потому что они не принимают те же аргументы и возвращают разные вещи. Это простое объяснение, если вы не понимаете дженерики.