25

I'm new to Swift and I've been going thru some tutorials and many of them define a function more than once with the same name.

I'm used to other programming languages where this cannot be done otherwise it throws an error.

Therefore I've checked the official Swift Manual and also checked the override keyword to see what I could get out of it, but still I cannot understand the following code:

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
}

From what I can see the function tableView is set in line #1 as well as in line #5, the only difference I noticed is that the first tableView function returns an Int and the second one returns an Object (UITableViewCell).

In this case I see from the result the second function is NOT overriding the first one.

What does this mean and why is it possible to define a function more than once with the same name without overriding it?

Mr.Web
  • 6,992
  • 8
  • 51
  • 86

4 Answers4

33

You are allowed to define two functions with the same name if they have different Types, or if they can be distinguished by their external parameter argument labels. The Type of a function is composed of the parameter Types in parentheses, followed by ->, followed by the return Type. Note that the argument labels are NOT a part of the function's Type. (But see UPDATE below.)

For example, the following functions both have the same name and are of Type (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
}

This will produce a compile-time error - changing the labels from a:b: to x:y: does not distinguish the two functions. (But see UPDATE below.)

Using Mr. Web's functions as examples:

// 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 { ... }

Function A and Function B above do not conflict because they are of different Types. Function A and Function C above do conflict because they have the same Type. Changing the parameter labels does not resolve the conflict if the Types remain the same. (See UPDATE below.)

override is a different concept altogether, and I think some of the other answers cover it, so I'll skip it.

UPDATE: Some of what I wrote above is incorrect. It is true that a function's parameter labels are not a part of it's Type definition, but they can be used to distinguish two functions that have the same Type, so long as the function has external labels that are different such that the compiler can tell which function you are trying to call when you invoke it. Example:

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"

So, the use of external labels in a function definition will allow functions with the same name and of the same type to compile. So, it appears that you can write multiple functions with the same name so long as the compiler can distinguish them by their types or by their external signature labels. I don't think internal labels matter. (But I hope someone will correct me if I'm wrong.)

Aaron Rasmussen
  • 13,082
  • 3
  • 42
  • 43
  • 2
    +1 for including the external label explanation. I found it in the simd library and, while cool, I was surprised it was allowed so went searching and found your answer. `public init(_ columns: [double3])` and `public init(rows: [double3])` are both valid initializers to `double3x3` and both have the same type signature. – Omegaman May 18 '16 at 00:38
  • More precisely: you would want to use parameter names (for internal definition) & argument labels (for external calling). Not the the parameter labels. (Please correct me if I'm wrong or not that precise I think I am) – SLN Sep 16 '16 at 13:01
  • It looks like there are more caveats to this. Namely, if a swift class extends an Obj-C class, or you have annotated both functions with @objc, you will be unable to overload based on the type, because the selectors are the same. Related, is it possible to exclude a method from being an objc selector when extending an objc class, i.e., the opposite annotation to @objc? – Daniel Brotherston Jan 30 '17 at 19:52
  • Answering my own question: "@nonobjc" seems to do the trick. – Daniel Brotherston Jan 30 '17 at 19:53
7

You're thinking of function overloading.

An excerpt from the Apple documentation here:

You can overload a generic function or initializer by providing different constraints, requirements, or both on the type parameters in the generic parameter clause. When you call an overloaded generic function or initializer, the compiler uses these constraints to resolve which overloaded function or initializer to invoke.

For example:

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
}

or:

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

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

This confusion is common especially if you're migrating from Objective-C to Swift for the first time. You should read about parameter names here.

Vatsal Manot
  • 17,695
  • 9
  • 44
  • 80
  • Thank you, I saw the documentation you've posted and also looked at the `The Swift Programming Language Book` from Apple. There is very little data about that, could you explain it better? – Mr.Web Dec 29 '14 at 13:57
  • Thank you, I've not learned about this `(...)` stuff yet.. Could you use a classic function type? (Like: `func process(a:Int)->Int` ) – Mr.Web Dec 29 '14 at 14:05
  • The functions in the question aren't anything to do with overloading or generics. – jrturton Dec 29 '14 at 14:07
7

In Swift, as in Objective-C, the parameters of a function form part of the definition. There aren't two functions called tableView, there is one function called tableView(tableView:, numberOfRowsInSection:) and one called tableView(tableView:, cellForRowAtIndexPath:)

jrturton
  • 118,105
  • 32
  • 252
  • 268
  • So the mistake would be if I declare 2 functions with the same name, return value and parameters, like `func one(i:Int) -> Int` and `func one(i:Int) -> Int`, am I right? – Mr.Web Dec 29 '14 at 14:09
  • 2
    That would be a compile-time error and the project would not build. – jrturton Dec 29 '14 at 14:10
0

The functions aren't the same they are different . Because they don't take the same arguments and return different things . This is the simple explanation if you don't understand generics.

Name
  • 179
  • 1
  • 8