questions about super.init and () - swift

I am confused when you have a child class that inherit from a parent class.
First question is why use super.init? I understand override init so it can override the values that was previously set from the parent but I don't understand the use of super.init..
Second question is why does init have parameters?
EDIT: Also why sometimes, the parent class also have a init??
class car {
var speed = 5
var model: String?
var age: Int?
}
class bmw: car {
override init() {
super.init()
model = "cat"
}
}

In your example, there is no good reason for calling super. But in general any class may have properties to initialize and other initial tasks to perform, and the rule, which says that a designated initializer of a subclass must call a superclass designated initializer, guarantees that this will happen coherently both for the subclass and for the superclass.

Related

Why is self used with init but not colour

I am taking an online class on swift and an example was shown. Why is self used with the init method call but not on colour?
class Car {
var colour = "Black"
var numberOfSeats = 5
var typeOfCar : CarType = .Coupe
init() {
}
convenience init (customerChosenColour : String) {
self.init()
colour = customerChosenColour
}
}
An init() runs when someone makes a new instance of that class like this:
var newInstanceOfCar = Car()
A convenience init allows you to create other initializers for certain use cases, like when there is a customerChosenColour that needs to be specified. It makes things more convenient in those cases.
The reason why self is used, is because when you create convenience init, you still need to call the "main" init, which is a property of self.
You can use self on colour, but it isn't necessary. You would use self.colour, if colour was ambiguous, like in this example:
class Car {
var colour = "Black"
var numberOfSeats = 5
var typeOfCar : CarType = .Coupe
init() {
}
convenience init (colour : String) {
self.init()
self.colour = colour
}
}
Notice how colour is a property of Car, but is also the name of the parameter for the convenience init. It would be confusing to write colour = colour.
So we use self to say that we want the variable in our class, self.colour, to be equal to the value of the parameter, colour.
As you wonder why self. cannot be omitted in self.init(), you can think of self.init() as whole is a special keyword just for convenience initializer. Same as super.init() as whole is a special keyword just for designated initializer. And Car.init()aka Car() is for creating a new instance. Calling init() itself without any receiver is not a valid call ever. So you can treat function call init() as nonexistence, self.init() is one keyword, super.init() is another keyword.
init() is not a member function, it is the initializer, some special code which will be run when creating new instances of that class. Don't treat initializers as regular member functions. They don't have the func keyword in front. They don't have the property of member functions. You can call member function on an instance but you cannot call initializer on an instance (Car().init() is not valid). self.init() dose NOT mean calling a function named init() from self.
class Foo
{
init(){}
func foo(){}
func bar()
{
self.foo() //valid. regular member function call
self.init() //invalid. init() is not a member function of the instance
}
}
Don't think self.init() like calling regular method from the same class, where self. can be omitted, but rather treat the whole thing as a special keyword that means "initialize this object with the designated initializer first".

Is final necessary for a singleton class in Swift?

To create a singleton class, I wrote something like this:
class SingletonEx{
var name = ""
private init(){}
static let sharedInstance = SingletonEx()
func instanceMethod(){
}
static func classMethod(){
}
}
Some tutorials say final is necessary while others just ignore final keyword. After I tried subclassing SingletonEx, I got the following results.
It seems I can't write an initializer for subclass, which means I can't use an override instance method in a subclass.
As far as I know, singleton definition is all about single instantiation and accessing instance methods through the only instance. So I don't think it is necessary to use final in the singleton definition. But both my teachers and some online tutorials say it is necessary.
I got confused, since you can't create a subclass instance anyway, even you override the instance methods, you can't use it or access it, what's the point to say final is necessary for a singleton class?
If I am wrong, please point out.
Super Class
First of all you need to know the properties and methods that are marked with private are just known to the Super class and Sub classes won't access them!
A class can inherit methods, properties, and other characteristics from another class. When one class inherits from another, the inheriting class is known as a subclass, and the class it inherits from is known as its superclass. Inheritance is a fundamental behavior that differentiates classes from other types in Swift.
Classes in Swift can call and access methods, properties, and subscripts belonging to their superclass and can provide their own overriding versions of those methods, properties, and subscripts to refine or modify their behavior. Swift helps to ensure your overrides are correct by checking that the override definition has a matching superclass definition.
In your case in SingletonEx class you market init with private which means that you can create object just in the body of the class! that means no one, no where, can't create an object of SingletonEx!
If you want to a method end up in Super Class and you don't want to Sub classes overide that method you need to mark that method with final which means it's not private but its available only from Super class!
Sub Class
When class Y Inheritance from SingletonEx which means that cant create an object outside of the class ! because Super class initializer is unavailable during init() method from class Y ! While you need to call the super.init() if you want to initialize an object from Y class !
if you remove private from private init() {} from SingletonEx class you be able to create object from SingletonEx class and also from Y class !
your code should looks like this :
Swift 4 :
class SingletonEx{
var name = ""
init(){}
static let sharedInstance = SingletonEx()
func instanceMethod(){
}
static func classMethod(){
}
}
class Y : SingletonEx {
private var yName = "Y name is : "
init(name:String) {
super.init()
self.name = self.yName + name
}
}
Usage :
override func viewDidLoad() {
super.viewDidLoad()
let yObject = Y.init(name: "badGirl :D ")
print(yObject)
// --> Output : Y name is : badGirl :D
}

Understanding init() when sub-classing in Swift

How can I add a custom initializer when inheriting from a class that already has an initializer?
What I have is a Vehicle class which has an itializer who takes an argument name. What I want to do is inherit from this Vehicleclass, create another initializer for the new class but keep using the existing initializer.
Base Class (No problem here):
class Vehicle{
var make:String
init(make:String){
self.make = make
}
}
New Class (Doesn't work):
// Not sure how to structure this class
class Car:Vehicle {
var engine:Double
override init(){
super.init()
}
init(engine:Double){
self.engine = engine
}
}
This is what I would like to be able to do... re-use the existing initializer plus the new one.
let cobalt = Car(make:"Chevy" engine: 2.5)
Any designated initializer in a subclass must call a designated initializer from its immediate superclass:
Initializer Delegation for Class Types
To simplify the relationships between designated and convenience
initializers, Swift applies the following three rules for delegation
calls between initializers:
Rule 1 A designated initializer must call a designated initializer
from its immediate superclass
...
From the Swift Language Guide - Initialization.
Hence, you could construct your designated initializer of Car to take two arguments, make and engine, and use the latter to inititalize the member property engine of the subclass, thereafter call the designated initializer of the superclass using the supplied make parameter (supplied to subclass initializer) as argument to the superclass initializer.
class Car: Vehicle {
var engine: Double
init(make: String, engine:Double){
self.engine = engine
super.init(make: make)
}
}

What's the purpose of initializing property values before calling super designated initializer in swift?

Here is my code:
class Base
{
init(){
print("Super!")
}
}
class Test : Base
{
internal var y:Int
convenience init(_ a:Int)
{
self.init()
print("\(a)")
}
override init()
{
super.init() //Error!!! Property 'self.y' not initialized at super.init call
y = 123
}
}
I think this should be compiled:
y is not visible inside class 'Base',whether order of initializations of y's and super class's doesn't really matter.
Your argument
I think this should be compiled:
y is not visible inside class 'Base',whether order of initializations
of y's and super class's doesn't really matter.
is not correct, that would not be safe.
The superclass init can call an instance
method which is overridden in the subclass. That is (at least one)
reason why all subclass properties must be initialized before super.init() is called.
A simple example:
class Base
{
init(){
print("enter Base.init")
setup()
print("leave Base.init")
}
func setup() {
print("Base.setup called")
}
}
class Test : Base
{
internal var y:Int
override init()
{
y = 123
print("before super.init")
super.init()
print("after super.init")
}
override func setup() {
print("Test.setup called")
print("y = \(y)")
}
}
Output:
before super.init
enter Base.init
Test.setup called
y = 123
leave Base.init
after super.init
As you can see, the y property of the subclass is accessed
during the super.init() call, even if it is not known to the
superclass.
It might be interesting to compare the situation in Objective-C
where self = [super initXXX] is always called first. This has the
consequence that property access self.prop in init/dealloc methods
is unsafe and direct access to the instance variable _prop is
recommended because the object may be in a "partially constructed state".
See for example Should I refer to self.property in the init method with ARC?.
So this is one of the issues which have been solved in Swift
(at the cost of stricter requirements).
From the documentation:
Safety check 1
A designated initializer must ensure that all of the
properties introduced by its class are initialized before it delegates
up to a superclass initializer.
As mentioned above, the memory for an object is only considered fully
initialized once the initial state of all of its stored properties is
known. In order for this rule to be satisfied, a designated
initializer must make sure that all its own properties are initialized
before it hands off up the chain.
Source: Swift Language Guide: Initialization
Just exchange the two lines in init
override init()
{
y = 123
super.init()
}

Why use required Initializers in Swift classes?

I am trying to understand the use of the required keyword in Swift classes.
class SomeClass
{
required init() {
// initializer implementation goes here
}
}
required doesn't force me to implement the method in my child-class. If I want to override the required designated initializer of my parent class I need to write required and not override. I know how it works but can not understand why I should do this.
What is the benefit of required?
As far as I can tell, languages like C# don't have something like this and work just fine with override.
It's actually just a way of satisfying the compiler to assure it that if this class were to have any subclasses, they would inherit or implement this same initializer. There is doubt on this point, because of the rule that if a subclass has a designated initializer of its own, no initializers from the superclass are inherited. Thus it is possible for a superclass to have an initializer and the subclass not to have it. required overcomes that possibility.
One situation where the compiler needs to be satisfied in this way involves protocols, and works like this:
protocol Flier {
init()
}
class Bird: Flier {
init() {} // compile error
}
The problem is that if Bird had a subclass, that subclass would have to implement or inherit init, and you have not guaranteed that. Marking Bird's init as required does guarantee it.
Alternatively, you could mark Bird as final, thus guaranteeing the converse, namely that it will never have a subclass.
Another situation is where you have a factory method that can make a class or its subclass by calling the same initializer:
class Dog {
var name: String
init(name: String) {
self.name = name
}
}
class NoisyDog: Dog {
}
func dogMakerAndNamer(whattype: Dog.Type) -> Dog {
let d = whattype.init(name: "Fido") // compile error
return d
}
dogMakerAndNamer is calling the init(name:) initializer on Dog or a Dog subclass. But how can the compiler be sure that a subclass will have an init(name:) initializer? The required designation calms the compiler's fears.
According to the documentation:
Write the required modifier before the definition of a class initializer to
indicate that every subclass of the class must implement that initializer
So yes, required does force all child classes to implement this constructor. However, this is not needed
if you can satisfy the requirement with an inherited initializer.
So if you have created more complex classes that cannot be fully initialized with a parent constructor, you must implement the require constructor.
Example from documentation (with some added stuff):
class SomeClass {
required init() {
// initializer implementation goes here
}
}
class SomeSubclass: SomeClass {
let thisNeedsToBeInitialized: String
required init() {
// subclass implementation of the required initializer goes here
self.thisNeedsToBeInitialized = "default value"
}
}
I want to draw an attention on another solution provided by Required, apart from Matt has given above.
class superClass{
var name: String
required init(){
// initializer implementation goes here
self.name = "Untitled"
}
}
class subClass: superClass {
var neakName: String = "Subclass Untitled"
}
let instanceSubClass = subClass()
instanceSubClass.name //output: "Untitled"
instanceSubClass.neakName //output: "Subclass Untitled"
As you can check in above example, I've declared required init() on superClass, init() initializer of superClass has inherited by default on subClass, So you able to create an instance of subClass let instanceSubClass = subClass().
But, suppose you want to to add one designated initializer on subClass to assign run time value to stored property neakName. Of course you can add it, but that will result to no initializers from the superClass will be inherited to subClass, So if you will create an instance of subClass you will create through its own designated initializer as below.
class superClass{
var name: String
init(){
// initializer implementation goes here
self.name = "Untitled"
}
}
class subClass: superClass {
var neakName: String = "Subclass Untitled"
init(neakName: String) {
self.neakName = neakName
}
}
let instanceSubClass = subClass(neakName: "Bobby")
instanceSubClass.name //output: "Untitled"
instanceSubClass.neakName //output: "Bobby"
Here above, you won't be able to create an instance of subClass by just subClass(), But if you want that every subclasses of superClass must have their own init() initializer to create direct instance by subClass(). Just place required keyword before init() on superClass, it will force you to add init() initializer on subClass too - as below.
class superClass{
var name: String
required init(){
// initializer implementation goes here
self.name = "Untitled"
}
}
class subClass: superClass {
var neakName: String = "Subclass Untitled"
init(neakName: String) {
self.neakName = neakName
}
} // Compiler error <------------ required `init()` must be provided by subClass.
let instanceSubClass = subClass(neakName: "Bobby")
instanceSubClass.name //output: "Untitled"
instanceSubClass.neakName //output: "Bobby"
SO, use required keyword before initializer on superclass, when you want all subclasses must have been implemented required initializer of superclass.
If you are trying to add you own initialiser in the sub class, then you have to follow certain things those were declared in super class. So it make sure that you will not forget to implement that required method. If you forget compiler will give you error // fatal error, we've not included the required init()
. Another reason is it creates a set of conditions that ever sub class should follow it the sub class is defining its own initialiser.