Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialMaximiliane Quel
Courses Plus Student 55,489 PointsUsing more than one parameter in the convenience initializer
When I try and set only the designer to default, I get an error and am prompted to use the override keyword. Is that correct? Do convenience initialisers only take one parameter? Or do I have to use override with a certain number of parameters? Is it the ratio? Or is that when I am supposed to use a convenience initialiser in another and how would that look? I am a bit confused.
class Clothing: Product {
var size = Size()
let designer: String
init(title: String, price: Double, designer: String){
self.designer = designer
super.init(title: title, price: price)
}
convenience override init(title: String, price: Double) {
self.init(title: title, price: price, designer: "Calvin Klein")
}
override func discountedPrice(_ percentage: Double = 10) -> Double {
return super.discountedPrice(percentage)
}
}
var tshirt = Clothing(title: "Vintage", price: 99)
2 Answers
Jhoan Arango
14,575 PointsHello Max:
So here is my explanation, I will try to make it as clear as possible.
Here is a great explanation of what a designated, and convenience initializers are used for, this comes from the e-book “The swift programming language” by apple. I recommend reading this as you go through tutorials, it will help you a lot.
“Designated Initializers and Convenience Initializers
Designated initializers are the primary initializers for a class. A designated initializer fully initializes all properties introduced by that class and calls an appropriate superclass initializer to continue the initialization process up the superclass chain.
Classes tend to have very few designated initializers, and it is quite common for a class to have only one. Designated initializers are “funnel” points through which initialization takes place, and through which the initialization process continues up the superclass chain.
Every class must have at least one designated initializer. In some cases, this requirement is satisfied by inheriting one or more designated initializers from a superclass, as described in Automatic Initializer Inheritance below.
Convenience initializers are secondary, supporting initializers for a class. You can define a convenience initializer to call a designated initializer from the same class as the convenience initializer with some of the designated initializer’s parameters set to default values. You can also define a convenience initializer to create an instance of that class for a specific use case or input value type.
You do not have to provide convenience initializers if your class does not require them. Create convenience initializers whenever a shortcut to a common initialization pattern will save time or make initialization of the class clearer in intent.”
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/us/k5SW7.l
class Product {
let title: String
var price: Double = 0.0
init(title: String, price: Double) {
self.title = title
self.price = price
}
func discountedPrice(percentage: Double) -> Double {
return price - (price * percentage / 100)
}
}
enum Size {
case Small, Medium, Large
init() { self = .Small }
}
class Clothing: Product {
var size = Size()
var designer: String
// Designated initializer
init(title: String, price: Double, designer: String){
self.designer = designer
super.init(title: title, price: price)
}
// convenient because we only use ONE title, and the rest is added automatically with default values.
convenience init(title: String) {
self.init(title: title, price: 9.99, designer: "Calvin Klein") // Default values
}
override func discountedPrice(percentage: Double) -> Double {
return super.discountedPrice(percentage)
}
}
The reason why we use a convenience initializer, is so that when we create an instance of that class, we don’t have to repeat something that can be already set by default. For example
var shirt = Clothing(title: "White Shirt") // using a convenient initializer
var jean = Clothing(title: "Blue Jean", price: 29.99, designer: "Levis") // using designated initializer
shirt.designer // will print Calvin Klein
jean.designer // will print Levis
Notice how with the convenient we only put the title and not worried about the rest since it’s already set with default values, when using the designated we have to give them values.
Now the reason why it’s telling you to use override, it’s because you are creating 2 identical initializers, in that case you can just change the name of one of the parameters, and create a different initializer. Like this
convenience init(title: String, price2: Double) { // Notice second parameter
self.init(title: title, price: price2, designer: "Calvin Klein")
}
// This will not give you that “override” error. But when you create an instance it will look
// like this.
var blackShirt = Clothing(title: "BlackShirt", price2: 59.99)
Hope you get it.
Maximiliane Quel
Courses Plus Student 55,489 PointsThat's amazing. Thank you!
Jhoan Arango
14,575 PointsYou are very welcome, hope that was clear and that you now understand. If you have anymore questions, please feel free to tag me @ jhoanarango
Maximiliane Quel
Courses Plus Student 55,489 PointsHi,
here is the entire thing:
class Product {
let title: String
var price: Double = 0.0
init(title: String, price: Double) {
self.title = title
self.price = price
}
func discountedPrice(percentage: Double) -> Double {
return price - (price * percentage / 100)
}
}
enum Size {
case Small, Medium, Large
init() { self = .Small }
}
class Clothing: Product {
var size = Size()
let designer: String
init(title: String, price: Double, designer: String){
self.designer = designer
super.init(title: title, price: price)
}
convenience override init(title: String, price: Double) {
self.init(title: title, price: price, designer: "Calvin Klein")
}
override func discountedPrice(_ percentage: Double = 10) -> Double {
return super.discountedPrice(percentage)
}
}
var tshirt = Clothing(title: "Vintage", price: 99)
It will take just title without the override when price is set to a default value in the convenience method:
convenience init(title: String) {
self.init(title: title, price: 99, designer: "Calvin Klein")
}
but as soon as I add the price to the parameter as above it will give me an error and ask for the override keyword ...
Jhoan Arango
14,575 PointsJhoan Arango
14,575 PointsHello Max:
Can you send me the rest of the code ? the product class.. This way I can explain better.
As far as I can see, you are not giving the convenience init the default values.