I was just setting up a class with a designated initializer and a convenience initializer to be able to pass in initializing properties beyond the defaults:
class Font { var name = "Arial" var size = 12 init() { } convenience init(name:String,size:Int) { self.init() self.name = name self.size = size } }
Great, all good so far. But sometimes a Font will be instantiated with a different name, but we want to leave the size as the default(or vice versa). Let’s add a default value to the name and size parameters in the convenience initializer:
convenience init(name:String="Arial",size:Int=12) {
Oh. You’ll see the obscure error on `self.init()`:
> Could not find an overload for ‘init’ that accepts the supplied arguments
What’s going on here? The error message isn’t very clear. If you comment out the offending line in the convenience initializer, and try to instantiate the class, you get a better idea of the problem:
Two initializers without parameters appear for the Font class. How does the compiler know which initializer you intend it to run with the following line?
var font = Font()
If you instantiate Font without parameters, you’ll see the error:
> Cannot invoke initializer for type ‘Font’ with no arguments”.
Still not a very clear error message, but you’ll probably be starting to get the idea why. You’ll see a much clearer error message if you set up two functions with the same name, one with a parameter with a default value:
class Planet { var name = "World" func greet()->String { return "Hello \(name)" } func greet(name:String = "World")->String { self.name = name return "Hello \(name)" } } var planet = Planet() planet.greet()
This time, you’ll see the error message:
> Ambiguous use of ‘greet’
Short and sweet, but I think it gets the point across much more clearly – ambiguity is the issue!
So stepping back a second – what’s a convenience initializer for? Supporting the designating initializer. But is a convenience initializer necessary if all of the parameters have default values? No!
class Font { var name = "Arial" var size = 12 init(name:String="Arial",size:Int=12) { self.name = name self.size = size } } var arial = Font() arial.name arial.size var comicSans = Font(name: "ComicSans", size: 10) comicSans.name comicSans.size var times = Font(name: "Times") times.name times.size var bigArial = Font(size: 48) bigArial.name bigArial.size
Leave a Reply