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
}
Related
I'm trying to understand what happens at a lower-level when we create the first instance of a Singleton object within the Singleton's own class declaration.
As I understand it, the static keyword allows the marked property or method to be shared across all instances of a class, which I'm sure has a role here that I'm not seeing fully.
Additionally, how does this work when we consider the instance's creation during compilation/runtime?
Here's an example of a Singleton class declaration:
class Person {
static let details = Person()
var name = "Alan Turing"
let age = "42"
}
I understand that the class and its properties will only be created once and that any reference to the class object will point back to that same point in memory. My confusion is specifically about why we create the Singleton's first instance within itself.
Basically static variables are class variables that are always accessible via the class itself.
I suggest reading a more in depth explanation of static here
By having a static variable inside the class that contains an object of the class itself you ensure that at runtime there already is an object of that class (or at least at the time of accessing Person.instance for the first time).
For a true singleton inside Swift it is mandatory to make the init of that class private though, like so:
public class Person {
static let instance = Person()
var name: String
let age: Int
private init() {
self.name = "Alan Turing"
self.age = 42
}
}
That way you ensure that there really is only one object present at any give time (hence the name singleton).
A class variable that contains the class itself, for example, the main property of the class DispatchQueue
Question 1
What kind of design pattern it is? Is this related to Singleton?
Question 2
How does the object initialized when referring this property?
Yes, it is the singleton pattern. It is all over swift like UserDefaults.standard, NotificationCenter.default, FileManager.default, ... For instance, URLSession.shared is defined in the apple docs as:
The shared singleton session object.
The singleton pattern makes sure that only one instance of the class is created. The class lazily creates its sole instance the first time it is requested and thereafter ensures that no other instance can be created.
Here is some sample code:
class MyClass {
static let shared = MyClass()
//Make the initializer private
private init(){}
//Here is a sample method
func doSomething() {
print("Doing something")
}
}
Making the initializer prevents the possibility of creating many instances, and thus the following line would yield an error:
let instance = MyClass() //MyClass initializer is inaccessible due to private protection level
To access the singleton use MyClass.shared:
let instance = MyClass.shared
instance.doSomething() //Prints: Doing something
For more details on the singleton pattern in Swift, you may look here and here.
world! I have an Actions class, where I hold all actions, animations and sound-plays in my sprite-kit game. So in all my SKNode, SKScene, SKSpriteNode classes I always initialize this Actions class. Is this good for performance? Or I have to initialize this one once, for example in GameViewController and then pass a copy of this class to all other classes, where I need?
As Fogmeister has mentioned in his comment you can use static methods to achieve this. This should also help with performance.
If you check the SKAction documentation you will notice that it uses class vars and methods as well.
In general if you do not need to instantiate a class multiple times, which your case is a perfect example of, than its best to use static/class methods or Singletons.
You can either use a class, struct or enum. I prefer to use enums because you cannot instantiate them by accident or need to add a private initialiser.
// Class
class SKActionHelper {
static var someProperty = ...
static func someMethod() {
...
}
}
// Struct
struct SKActionHelper {
static var someProperty = ...
static func someMethod() {
...
}
}
// Enum
enum SKActionHelper {
static var someProperty = ...
static func someMethod() {
...
}
}
Now you can call those properties or methods anywhere in your project and do not need to instantiate the class each time.
SKActionHelper.someProperty = ...
SKActionHelper.someMethod()
Hope this helps
I have read the Swift docs and searched here, but I still am not sure about how to implement a class hierarchy where each subclass sets custom value for an inherited static property; that is:
Base class defines a static property: all instances share the same value.
Subclass overrides the static property: all instances share the same value, which is different form that of the base class.
Can the property be stored?
Also, How should I access the value of the property from within an instance method (regardless of the particular class), and get the correct value everytime? will the following code work?
class BaseClass
{
// To be overridden by subclasses:
static var myStaticProperty = "Hello"
func useTheStaticProperty()
{
// Should yield the value of the overridden property
// when executed on instances of a subclass:
let propertyValue = self.dynamicType.myStaticProperty
// (do something with the value)
}
You are so close to being there, except that you can't override a static property in a subclass — that is what it means to be static. So you'd have to use a class property, and that means it will have to be a computed property — Swift lacks stored class properties.
So:
class ClassA {
class var thing : String {return "A"}
func doYourThing() {
print(type(of:self).thing)
}
}
class ClassB : ClassA {
override class var thing : String {return "B"}
}
And let's test it:
ClassA().doYourThing() // A
ClassB().doYourThing() // B
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.