Swift – Classes
Last Updated :
09 Feb, 2024
Classes and Objects are building blocks of the Object-Oriented-Programming Paradigm. Class is a logical entity or a user-defined data type that has its own data members and member functions which can be accessed inside the class or outside it depending upon the access control allowed on each member. A class in Swift acts like a blueprint or a template for every object and it defines its behavior, methods, and properties for a group of objects. Classes in Swift help us define the object’s behavior, by allowing us to create constants, references, variables, and functions that are specific to its type creating a user-defined data type.
This article focuses on discussing the creation of classes, types of classes, and accessing members of classes.
Syntax:
<access_control> class <class_name>{
var property1 : <data_type> // variable declaration
let property2 : <data_type> // Constant declaration
init(property1:data_type, property2:data_type)
{
self.property1 = property1;
self.property2 = property2;
}
func function_name() {}
}
Syntax for Creating Class Instance:
var myObj1 = className()
let myObj2 = className(property1:value1, property2:value2)
Components of a Class in Swift
Access Control
These are used to control the visibility and accessibility of the properties, functions, and other members of our class. These are optional. Following are the access specifiers provided in Swift:
- internal: If no access control is specified then this is the default access control in Swift which means, that the class is accessible in the current module (your application or framework).
- public: This will allow the class to be accessible through any source file in the same module and other modules that import the module in which this class resides. You must be cautious while using this as it exposes the class to the outside world.
- fileprivate: This makes the class accessible in the source file in which it is defined and the extension defined in the same source file. The object reference that we will create for this type of class will also have to be declared as fileprivate.
- private: This is the most secure access control which limits the visibility of the class only in the defining source file. The object reference that we will create for this type of class will also have to be declared as fileprivate.
- open: This provides access and visibility to the same module as well as the other modules that import it and allows the class to be inherited and methods to be overridden by other subclasses outside the module.
Properties
Properties are variables or constants that are specific to the instance or the class (if declared static). They generally store the data inputted into the class’s instance.
Initializers
Initializers are similar to constructors that are used to set the initial state of an object of a specific type. The initializers can be overloaded, and if no initializer is given by the user then the swift compiler will insert one by itself.
- self keyword is used inside an init() to access the properties of the current instance and perform operations on them.
- It is similar to this keyword in other OOP languages.
Functions
Functions in Swift are declared using the ‘func’ keyword followed by a parenthesis and a pair of curly braces. In swift, every method must have a body if it’s declared inside a class.
Just like any other programming language, the keyword – ‘class’ followed by the name of the class and a pair of curly braces {} is used to define a class. And access all its properties and functions through its object using the dot (.) operator.
Example of Swift Class
Swift
class Person {
var name : String
var age : Int
init (name: String , age: Int ) {
self .name = name
self .age = age
}
func personDetails(){
print ( "Name :" , self .name, ", Age :" , age)
}
}
var myObj = Person(name : "Adwitiya Mourya" , age : 23)
myObj.personDetails()
|
Output:
Explanation:
- We’ve simply created a class named ‘Person’.
- properties: name and age of String and Int type respectively.
- init() is a special method similar to the constructor which sets up an initial state of our object. If no init() method is provided, then the compiler will provide a default one that takes no argument.
- Then we create an instance of this class ‘myObject’, print its properties and call the personDetails Method through that instance.
Note:
The actual documentation of SWIFT says – classes and structure should be named in ‘UpperCamelCase’ and the variables and properties of a class should be named in – ‘lowerCamelCase’. That way, we can easily differentiate between class names and variable names.
Creating Instance of a Class
In Swift, there are 2 ways to create an instance of a class:
1. Create a Constant Instance using the ‘let’ Keyword
The reference to the instance cannot be changed, but its properties can be modified.
Swift
class GeeksForGeeks {
var property1: Int = 0
var property2: String = "Hello Geek"
}
let MyConstandInstance = GeeksForGeeks()
var MyVariableInstance = GeeksForGeeks()
MyConstandInstance = MyVariableInstance
|
The above code will not compile because we’re trying to change the reference of the constant instance.
Explanation:
- Using ‘let’ we create an immutable reference.
- We create another variable reference (mutable).
- Then we try to modify the constant reference, but it will generate an error saying “Change ‘let’ to ‘var’ to make it mutable”.
- However, we can still change the property of our constant reference, it’s valid and won’t generate any error.
2. Create a Variable Instance using the ‘var’ Keyword
This creates variable objects, whose reference as well as the properties can be changed.
Swift
class GeeksForGeeks {
var num: Int = 0
var demoString: String = "Hello Geek"
}
var MyVariableInstance1 = GeeksForGeeks()
var MyVariableInstance2 = GeeksForGeeks()
MyVariableInstance1 = MyVariableInstance2
|
Explanation:
- Using ‘var’ we create 2 mutable references.
- Note that here, we changed assigned the MyVariableInstance2 to MyVariableInstance1 which is valid here and our code will compile error-free.
- There won’t be any output because we’re not printing anything.
Types of Classes
1. Non-Final Class (Simple Class)
A simple class is a logical entity that is a blueprint for all its instances, and it can be inherited by other classes and various OOP functionalities can be implemented in it. As we saw in the previous example.
Swift
class GeeksForGeeks {
func printName() {
fatalError( "This method is to be overridden by subclasses" )
}
}
class Geek: GeeksForGeeks {
override func printName() {
print ( "Hello Geek !" )
}
}
var MyObj = Geek()
MyObj.printName()
|
Output:
Explanation:
- We created 2 classes – GeeksForGeeks and Geek.
- GeeksForGeeks is a parent class, and Geek is a child class.
- Then we override the method – printName().
- The fatalError() in our code will enforce the overriding behavior by the sub-classes. Else our program will terminate with a runtime error if not overridden.
- As this is a normal class, every oops functionality is operable in it.
2. Final Class
A Final Class is a type of class that cannot be inherited by other classes. A class may be marked as final to maintain a degree of control over an object’s state and behavior and prevent further modifications. If you try to inherit any class marked as final, then it will generate a compiler error.
Swift
final class GeeksForGeeks {
func printName() {
fatalError( "This method is to be overridden by subclasses" )
}
}
class Geek: GeeksForGeeks {
override func printName() {
print ( "Hello Geek !" )
}
}
|
Explanation:
- Created a Final class – GeeksForGeeks, then we tried to inherit in class – Geek.
- This will generate a compiler error because the class – GeeksForGeeks is marked as “Final”.
3. Abstract Class (Protocols)
Unlike other programming languages like C++ and Java, in Swift, we don’t have abstract classes, but to achieve the same behavior we have protocols. Protocols provide us a way to implement interface behavior that is, a template for methods, properties (variables), and other functionality without providing its implementation.
They help promote code reusability, interoperability, and flexibility in Swift Programming.
Syntax:
protocol protocol_name{
var property: data_type { get/set }
func method_name()
}
Note:
It is necessary to provide { get/set } getters and setters inside protocols that are read-only, write-only, or read-write indicating their values will be computed or stored by the implementing classes
Example:
Swift
protocol Vehicle {
var type: String { get }
var noOfWheels: Int { get }
func printVehicleDetails()
}
class Car: Vehicle {
var noOfWheels: Int {
return 4
}
var type: String {
return "car"
}
func printVehicleDetails() {
print ( "Details of Vehicle - Type:" , type, ", No Of Wheels :" , noOfWheels)
}
}
class Bike: Vehicle {
var type: String {
return "Bike"
}
var noOfWheels: Int {
return 2
}
func printVehicleDetails() {
print ( "Details of Vehicle - Type:" , type, ", No Of Wheels :" , noOfWheels)
}
}
var bike = Bike()
var car = Car()
bike.printVehicleDetails()
car.printVehicleDetails()
|
Output:
Explanation:
- We create a protocol named – Vehicle, in which we have defined properties: No Of Wheels and Type (of the vehicle) and a method to print the vehicle’s details.
- These properties and methods are requirements defined by the protocol that the conforming class must adhere to and give implementation for the same.
- The Bike and Car class conforms to the Vehicle Protocol that is, implementing all the required functionalities provided in it.
Share your thoughts in the comments
Please Login to comment...