I have the following class in Swift 4:
class AClass {
var add: (Int) -> Int {
return {
num in
return num + 1
}
}
func add(_ num: Int) -> Int {
return num + 20
}
}
Note that the variable and function have the same name 'add'.
Now in some other place I have this code:
let a = AClass()
print(a.add(1))
I have run this code, and the result is 2 (which means the variable's block is called).
So here are the questions:
Does the compiler always get the variable rather than call the function?
Is there any way to call the function?
Variables and functions have separate name spaces, which means a variable and a function can have the same name, such as value and value(), and Mata will not confuse them.
No variable name should not has same name with **any** class name.
Yes it's fine, mainly because, syntactically , they're used differently.
Bottom line: you can't have two things simultaneously with the same name, be it a function, an integer, or any other object in Python. Just use a different name.
While both the property and method share the same base name add
, they have different full names. The method's full name is add(_:)
due to the fact that it has a parameter (with no argument label), and the property's full name is just add
. The fact that their full names differ is what allows them to overload each other.
If the method had no parameters, then the compiler would not have allowed the overload, as their full names are now both add
and therefore conflict:
class AClass {
var add: () -> Int {
return {
return 1
}
}
func add() -> Int { // error: Invalid redeclaration of 'add()'
return 2
}
}
Does the compiler always get the variable rather than call the function?
Assuming they have the same function type (such as in your example), then yes. There is an overload ranking rule that favours variables over functions:
// If the members agree on instance-ness, a property is better than a // method (because a method is usually immediately invoked). if (!decl1->isInstanceMember() && decl2->isInstanceMember()) score1 += weight; else if (!decl2->isInstanceMember() && decl1->isInstanceMember()) score2 += weight; else if (isa<VarDecl>(decl1) && isa<FuncDecl>(decl2)) score1 += weight; else if (isa<VarDecl>(decl2) && isa<FuncDecl>(decl1)) score2 += weight;
lib/Sema/CSRanking.cpp
In order to call the method, you can use refer to it by its full name, for example:
let a = AClass()
print(a.add(_:)(1)) // 21
In Swift, instance methods are curried functions. Which means your add
method is actually
static func add(_ self: AClass) -> (Int) -> Int
This is why the property gets chosen over the function. Calling AClass.add(a)(1)
yelds the expected result, the function gets called.
Now, why does the compiler allows this name clashing if the first place? I'm not sure, but I assume it has to do with the fully qualified name of those two entities. The property is simply add
, while the function is add(_:)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With