Tcl – Data Types ”; Previous Next The primitive data-type of Tcl is string and often we can find quotes on Tcl as string only language. These primitive data-types in turn create composite data-types for list and associative array. In Tcl, data-types can represent not only the simple Tcl objects, but also can represent complex objects such as handles, graphic objects (mostly widgets), and I/O channels. Let”s look into the details about each of the above. Simple Tcl Objects In Tcl, whether it is an integer number, boolean, floating point number, or a string. When you want to use a variable, you can directly assign a value to it, there is no step of declaration in Tcl. There can be internal representations for these different types of objects. It can transform one data-type to another when required. The syntax for assigning value to variable is as follows − Live Demo #!/usr/bin/tclsh set myVariable 18 puts $myVariable When the above code is executed, it produces the following result − 18 The above statement will create a variable name myVariable and stores it as a string even though, we have not used double quotations. Now, if we try to make an arithmetic on the variable, it is automatically turned to an integer. A simple example is shown below − Live Demo #!/usr/bin/tclsh set myVariable 18 puts [expr $myVariable + 6 + 9] When the above code is executed, it produces the following result − 33 One important thing to note is that, these variables don”t have any default values and must be assigned value before they are used. If we try to print using puts, the number is transformed into proper string. Having two representations, internal and external, help Tcl to create complex data structures easily compared to other languages. Also, Tcl is more efficient due to its dynamic object nature. String Representations Unlike other languages, in Tcl, you need not include double quotes when it”s only a single word. An example can be − Live Demo #!/usr/bin/tclsh set myVariable hello puts $myVariable When the above code is executed, it produces the following result − hello When we want to represent multiple strings, we can use either double quotes or curly braces. It is shown below − Live Demo #!/usr/bin/tclsh set myVariable “hello world” puts $myVariable set myVariable {hello world} puts $myVariable When the above code is executed, it produces the following result − hello world hello world List List is nothing but a group of elements. A group of words either using double quotes or curly braces can be used to represent a simple list. A simple list is shown below − Live Demo #!/usr/bin/tclsh set myVariable {red green blue} puts [lindex $myVariable 2] set myVariable “red green blue” puts [lindex $myVariable 1] When the above code is executed, it produces the following result − blue green Associative Array Associative arrays have an index (key) that is not necessarily an integer. It is generally a string that acts like key value pairs. A simple example is shown below − Live Demo #!/usr/bin/tclsh set marks(english) 80 puts $marks(english) set marks(mathematics) 90 puts $marks(mathematics) When the above code is executed, it produces the following result − 80 90 Handles Tcl handles are commonly used to represent files and graphics objects. These can include handles to network requests and also other channels like serial port communication, sockets, or I/O devices. The following is an example where a file handle is created. set myfile [open “filename” r] You will see more detail on files in the Tcl file I/O chapter. Print Page Previous Next Advertisements ”;
Category: Computer Programming
Swift – Generics
Swift – Generics ”; Previous Next Swift provides a special feature known as ‘Generic” to write flexible and reusable functions and types that can work well with any other type. Generics are used to avoid duplication and to provide abstraction. Swift has some standard libraries that are built with generics code. Arrays and dictionary types belong to a generic collection. So, we are allowed to create an array that holds a String value or can able to create an array that holds an int value. Similarly, for the dictionary. Example func exchange(inout a: Int, inout b: Int) { let temp = a a = b b = temp } var numb1 = 100 var numb2 = 200 print(“Before Swapping values are: (numb1) and (numb2)”) exchange(&numb1, &numb2) print(“After Swapping values are: (numb1) and (numb2)”) Output It will produce the following output − Before Swapping values are: 100 and 200 After Swapping values are: 200 and 100 Generic Functions Generic functions are special functions that can be used to access any data type like ”Int” or ‘String’ while maintaining the type safety. Or we can say that generic functions can work with different types without specifying the actual type at the time of declaration. Example In the following example, The function exchange() is used to swap values described in the above program and <T> is used as a type parameter. For the first time, function exchange() is called to return ”Int” values and the second call to the function exchange() will return ”String” values. Multiple parameter types can be included inside the angle brackets separated by commas. func exchange<T>(_ a: inout T, _ b: inout T) { let temp = a a = b b = temp } var numb1 = 100 var numb2 = 200 print(“Before Swapping Int values are: (numb1) and (numb2)”) exchange(&numb1, &numb2) print(“After Swapping Int values are: (numb1) and (numb2)”) var str1 = “Generics” var str2 = “Functions” print(“Before Swapping String values are: (str1) and (str2)”) exchange(&str1, &str2) print(“After Swapping String values are: (str1) and (str2)”) Output It will produce the following output − Before Swapping Int values are: 100 and 200 After Swapping Int values are: 200 and 100 Before Swapping String values are: Generics and Functions After Swapping String values are: Functions and Generics Type Parameters Type parameters are named as user-defined to know the purpose of the type parameter that it holds. Swift provides <T> as a generic type parameter name. However type parameters like Arrays and Dictionaries can also be named as key, values to identify that they belong to the type ‘Dictionary”. We are allowed to provide more than one type parameter by writing multiple type parameter names in the angle brackets, where each name is separated by a comma. Example // Generic Types struct TOS<T> { var items = [T]() mutating func push(item: T) { items.append(item) } mutating func pop() -> T? { return items.popLast() } } var tos = TOS<String>() tos.push(item: “Swift 4”) print(tos.items) tos.push(item: “Generics”) print(tos.items) tos.push(item: “Type Parameters”) print(tos.items) tos.push(item: “Naming Type Parameters”) print(tos.items) if let deletetos = tos.pop() { print(“Popped item: (deletetos)”) } else { print(“The stack is empty.”) } Output It will produce the following output − [“Swift 4”] [“Swift 4”, “Generics”] [“Swift 4”, “Generics”, “Type Parameters”] [“Swift 4”, “Generics”, “Type Parameters”, “Naming Type Parameters”] Popped item: Naming Type Parameters Generic Type and Extending a Generic Type In Swift, we are allowed to define generic types to create flexible and reusable structures, classes or enumerations that can easily work with any data type. Also, we are allowed to extend the functionality of generic types using the extension keyword. Example struct TOS<T> { var items = [T]() mutating func push(item: T) { items.append(item) } mutating func pop() -> T { return items.removeLast() } } var tos = TOS<String>() tos.push(item: “Swift 4”) print(tos.items) tos.push(item: “Generics”) print(tos.items) tos.push(item: “Type Parameters”) print(tos.items) tos.push(item: “Naming Type Parameters”) print(tos.items) extension TOS { var first: T? { return items.isEmpty ? nil : items[items.count – 1] } } if let first = tos.first { print(“The top item on the stack is (first).”) } Output It will produce the following output − [“Swift 4”] [“Swift 4”, “Generics”] [“Swift 4”, “Generics”, “Type Parameters”] [“Swift 4”, “Generics”, “Type Parameters”, “Naming Type Parameters”] The top item on the stack is Naming Type Parameters. Type Constraints Swift allows ”type constraints” to specify whether the type parameter inherits from a specific class, or to ensure protocol conformance standard. We are allowed to use them with classes and protocols to specify more complex requirements. While creating custom generic types we are allowed to create our own type constraints. Syntax Following is the syntax for the type constraints − Func functionName<T: className, U: protocolName>(variable1: T, variable2: U){ // Function body } Example // A generic function with a type constraint func show<T: CustomStringConvertible>(item: T) { print(item.description) } let str = “Welcome Swift” let number = 22 show(item: str) show(item: number) Output It will produce the following output − Welcome Swift 22 Where Clauses Type constraints enable the user to define requirements on the type parameters associated with a generic function or type. For defining requirements for associated types ”where” clauses are declared as part of the type parameter list. ”where” keyword is placed immediately after the list of type parameters followed by constraints of associated types, and equality relationships between types and associated types. Example protocol Container { typealias ItemType mutating func append(item: ItemType) var count: Int { get } subscript(i: Int) -> ItemType { get } }
Swift – Protocols
Swift – Protocols ”; Previous Next Protocols provide a blueprint for Methods, properties and other requirements functionality. It is just described as a methods or properties skeleton instead of an implementation. Methods and properties implementation can further be done by defining classes, functions and enumerations. Conformance of a protocol is defined as the methods or properties satisfying the requirements of the protocol. Defining Protocols in Swift In Swift, the definition of the protocol is quite similar to the class, structure or enumeration. A protocol is defined using the protocol keyword. Syntax Following is the syntax for the protocol − protocol SomeProtocol { // protocol definition } Protocols are declared after the class, structure or enumeration type names. Single and multiple protocol declarations are also possible. If multiple protocols are defined they have to be separated by commas. struct SomeStructure: Protocol1, Protocol2 { // structure definition } When a protocol has to be defined for a superclass, the protocol name should follow the superclass name with a comma. class SomeClass: SomeSuperclass, Protocol1, Protocol2 { // class definition } Property, Method and Initialization Requirements A protocol requires any conforming type which can provide property, method and initialization. Property Requirements − A protocol is used to specify a particular class type property or instance property. It only specifies the type or instance property rather than specifying whether it is a stored or computed property. Also, specify whether the property is ”gettable” or ”settable”. Property requirements are declared by ”var” keyword as property variables. {get set} is used to declare gettable and settable properties after their type declaration. Gettable is mentioned by {get} property after their type declaration. Syntax The following syntax is for defining properties in protocol − protocol SomeProtocol { var propertyName : Int {get set} } Method Requirements − A protocol is used to specify particular type methods or instance methods. It only contains the definition part without curly braces and body. It allows methods to have variadic parameters. Syntax The following syntax is for defining methods in protocol − protocol SomeProtocol { func methodName(parameters) } Mutating Method Requirements − If you want to specify a mutating method in the protocol then use the mutating keyword before the definition of the method. It allows structure and enumeration to adopt the protocol with the mutating method. Syntax The following syntax is for defining mutating methods in protocol − protocol SomeProtocol { mutating func methodName(parameters) } Initializer Requirements: A protocol is also used to specify an initializer that will implemented by conforming types. It only contains the definition part just like the normal initializers, but without and curly braces and a body. We can specify either designated or convenience initializers. Also, the class or structure that conforms to the protocol must use the required modifier before the implementation of the initializer. Protocol conformance is ensured on all subclasses for explicit or inherited implementation by ”required” modifier. When a subclass overrides its superclass initialization requirement it is specified by the ”override” modifier keyword. Syntax The following syntax is for defining initializers in protocol − protocol SomeProtocol { init(parameters) } Example Swift program to create a protocol that conforms by a class. // Protocol protocol classa { // Properties var marks: Int { get set } var result: Bool { get } // Method func attendance() -> String func markssecured() -> String } // Protocol protocol classb: classa { // Properties var present: Bool { get set } var subject: String { get set } var stname: String { get set } } // Class that conform Protocol class classc: classb { var marks = 96 let result = true var present = false var subject = “Swift 4 Protocols” var stname = “Protocols” func attendance() -> String { return “The (stname) has secured 99% attendance” } func markssecured() -> String { return “(stname) has scored (marks)” } } // Instance of class let studdet = classc() studdet.stname = “Swift 4″ studdet.marks = 98 // Accessing methods and properties print(studdet.markssecured()) print(studdet.marks) print(studdet.result) print(studdet.present) print(studdet.subject) print(studdet.stname) Output It will produce the following output − Swift 4 has scored 98 98 true false Swift 4 Protocols Swift 4 Example Swift program to create a protocol with mutating method requirements. // Protocol protocol daysofaweek { // Mutating method mutating func display() } // Enumeration that conforms to the Protocol enum days: daysofaweek { case sun, mon, tue, wed, thurs, fri, sat mutating func display() { switch self { case .sun: print(“Sunday”) case .mon: print(“Monday”) case .tue: print(“Tuesday”) case .wed: print(“Wednesday”) case .thurs: print(“Thursday”) case .fri: print(“Friday”) case .sat: print(“Saturday”) } } } // Instance of enumeration var res = days.wed res.display() Output It will produce the following output − Wednesday Example Swift program to create a protocol with an initializer that conforms to the class. // Protocol protocol tcpprotocol { // Initializer init(no1: Int) } class mainClass { var no1: Int // local storage init(no1: Int) { self.no1 = no1 // initialization } } // Class that conform protocol class subClass: mainClass, tcpprotocol { var no2: Int init(no1: Int, no2 : Int) { self.no2 = no2 super.init(no1:no1) } // Requires only one parameter for convenient method required override convenience init(no1: Int) { self.init(no1:no1, no2:0) } } // Class instances let obj1 = mainClass(no1: 20) let obj2 = subClass(no1: 30, no2: 50) print(“res is: (obj1.no1)”) print(“res is: (obj2.no1)”) print(“res is: (obj2.no2)”) Output It will produce the following output − res is: 20 res is: 30 res is: 50
Swift – Extensions
Swift – Extensions ”; Previous Next What are Extensions in Swift? Swift provides a special feature known as extension. Extensions are used to add new functionalities in the existing class, structure, enumeration or protocol type without overriding or modifying the existing code. This feature is useful when we want to extend the functionality of types that we cannot modify, such as third-party libraries, etc. Extensions are static additions to the type they are not dynamic. Also, they cannot add stored properties with default values. The following are the functionalities provided by the extensions − Adding computed properties and computed type properties Defining instance and type methods Providing new initializers Defining subscripts Defining and using new nested types Making an existing type conform to a protocol Defining Extensions in Swift Extensions are declared with the help of the extension keyword. Syntax Following is the syntax for the extension − extension SomeType { // Adding new functionality } Existing type can also be added with extensions to make it a protocol standard and its syntax is similar to that of classes or structures. extension SomeType: SomeProtocol, AnotherProtocol { // Describe protocol requirements } Extensions with Computed Properties Computed ”instance” and ”type” properties can also be extended with the help of extensions. Computed properties are those properties that do not store a value instead, they provide a getter and setter to retrieve and set other properties and values. Example Swift program to demonstrate how to add new functionality in the computed properties using the extension. // Adding new functionality to the computed property using an extension extension Int { var add: Int {return self + 100 } var sub: Int { return self – 10 } var mul: Int { return self * 10 } var div: Int { return self / 5 } } let addition = 3.add print(“Addition is (addition)”) let subtraction = 120.sub print(“Subtraction is (subtraction)”) let multiplication = 39.mul print(“Multiplication is (multiplication)”) let division = 55.div print(“Division is (division)”) let mix = 30.add + 34.sub print(“Mixed Type is (mix)”) Output It will produce the following output − Addition is 103 Subtraction is 110 Multiplication is 390 Division is 11 Mixed Type is 154 Extension with Initializers Swift provides the flexibility to add new initializers to an existing type using extensions. The user can add their own custom types to extend the types already defined and additional initialization options are also possible. Extensions support only init(). deinit() is not supported by the extensions. Example Swift program to demonstrate how to add new functionality in the initializer using the extension. struct sum { var num1 = 100, num2 = 200 } struct diff { var no1 = 200, no2 = 100 } struct mult { var a = sum() var b = diff() } let calc = mult() print (“Inside mult block (calc.a.num1, calc.a.num2)”) print(“Inside mult block (calc.b.no1, calc.b.no2)”) let memcalc = mult(a: sum(num1: 300, num2: 500),b: diff(no1: 300, no2: 100)) print(“Inside mult block (memcalc.a.num1, memcalc.a.num2)”) print(“Inside mult block (memcalc.b.no1, memcalc.b.no2)”) extension mult { init(x: sum, y: diff) { let X = x.num1 + x.num2 let Y = y.no1 + y.no2 } } let a = sum(num1: 100, num2: 200) print(“Inside Sum Block:( a.num1, a.num2)”) let b = diff(no1: 200, no2: 100) print(“Inside Diff Block: (b.no1, b.no2)”) Output It will produce the following output − Inside mult block (100, 200) Inside mult block (200, 100) Inside mult block (300, 500) Inside mult block (300, 100) Inside Sum Block:(100, 200) Inside Diff Block: (200, 100) Extension with Methods New instance methods and type methods can be added further to the subclass with the help of extensions. Example Swift program to demonstrate how to add new functionality in the methods using the extension. extension Int { func topics(summation: () -> ()) { for _ in 0..<self { summation() } } } 4.topics({ print(“Inside Extensions Block”) }) 3.topics({ print(“Inside Type Casting Block”) }) Output It will produce the following output − Inside Extensions Block Inside Extensions Block Inside Extensions Block Inside Extensions Block Inside Type Casting Block Inside Type Casting Block Inside Type Casting Block Extension with Mutating Instance Methods We can also add new functionality in the mutating instance methods of structure and enumeration using the extension. Example Swift program to demonstrate how to add new functionality in the mutating methods using the extension. extension Double { mutating func square() { let pi = 3.1415 self = pi * self * self } } var Trial1 = 3.3 Trial1.square() print(“Area of circle is: (Trial1)”) var Trial2 = 5.8 Trial2.square() print(“Area of circle is: (Trial2)”) var Trial3 = 120.3 Trial3.square() print(“Area of circle is: (Trial3)”) Output It will produce the following output − Area of circle is: 34.210935 Area of circle is: 105.68006 Area of circle is: 45464.070735 Extension with Subscripts Adding new subscripts to already declared instances can also be possible with extensions. Example Swift program to demonstrate how to add new functionality in the subscript using the extension. extension Int { subscript(var multtable: Int) -> Int { var no1 = 1 while multtable > 0 { no1 *= 10 –multtable } return (self / no1) % 10 } } print(12[0]) print(7869[1]) print(786543[2]) Output It will produce the following output − 2 6 5 Extension with Nested Types Nested types for class, structure and enumeration instances can also be extended with the help of extensions. Example
Swift – Methods
Swift – Methods ”; Previous Next Methods are the functions of a particular type, such as class, structure or enumeration. They define the behavior and functionality for instances of a type. They are generally accessed by the instances. Swift also supports type methods that are associated with the type itself. Instance Methods in Swift In Swift, instance methods are the functions that belong to the specific instance of a class, structure or enumeration. They are called on an instance of the type and can access and modify instance properties or other instance methods, or also add functionality related to the instance”s need. The syntax of the instance method is the same as the function. Instance method can also have, parameters, return type, parameter names, and argument labels. It can be written inside the {} curly braces. It has implicit access to methods and properties of the type instance. An instance method is called only using the instance of that particular type, we are not allowed to call an instance method without any instance. Syntax Following is the syntax of the instance method- func methodname(Parameters) -> returntype { Statement1 Statement2 — Statement N return parameters } Instance methods are accessed with ”.” dot syntax. instanceName.methodName() Example // Defining a class class Calculations { // Properties let a: Int let b: Int let res: Int // Initializer init(a: Int, b: Int) { self.a = a self.b = b res = a + b } // Instance method func tot(c: Int) -> Int { return res – c } // Instance method func result() { print(“Result is: (tot(c: 20))”) print(“Result is: (tot(c: 50))”) } } // Creating and initializing the instance of the class let pri = Calculations(a: 600, b: 300) // Accessing the instance method pri.result() Output It will produce the following output − Result is: 880 Result is: 850 Mutating Instance Method In Swift, structures and enumerations are value types, which means we cannot alter the properties inside the instance method. So to modify the properties inside a method we need to specify that method as a mutating method using the mutating keyword and the changes made by the method in its properties will written back to the original structure when the method ends. We can only mutate methods of structure and enumeration but not class because a class is a reference type so their properties can be modified without using mutating keyword. Also, we cannot call a mutating method on a constant of structure type. Syntax Following is the syntax of the mutating instance method − mutating func methodname(Parameters) -> returntype { Statement } Example Swift program to demonstrate the mutating method in structure. // Defining a structure struct CalculateSum { // Properties var num1 = 1 var num2 = 1 // Instance method func sum() -> Int { return num1 + num2 } // Mutating instance method mutating func increment(res: Int) { num1 *= res num2 *= res print(“New Number 1 is “, num1) print(“New Number 2 is “, num2) } } // Creating and initializing the instance of structure var obj = CalculateSum(num1: 10, num2: 12) // Calling mutating method obj.increment(res: 10) // Calling instance method print(“Sum is “, obj.sum()) Output It will produce the following output − New Number 1 is 100 New Number 2 is 120 Sum is 220 Assigning Instance to self within a Mutating Method In mutating methods, we are allowed to assign a new instance to the implicit self property. It will replace the existing instance with the new instance. While assigning a new instance to the self always be careful because it changes the state of the instance and any reference related to the original instance will not reflect the changes. Example Swift program to demonstrate how to assign an instance to self within a mutating method. // Defining a structure struct Student { var age: Int var name: String // Mutating method that assigns a new instance to self mutating func newValue() { self = Student(age: 23, name: “Jyoti”) } } // Creating an instance of the Student structure var obj = Student(age: 22, name: “Poonam”) // Calling the mutating method obj.newValue() // Displaying the updated values print(“New age: (obj.age), New name: (obj.name)”) Output It will produce the following output − New age: 23, New name: Jyoti Method Argument label and Parameter name in Swift Just like a function, a method can also have labels and names for its arguments and parameters. These labels and names provide a clear and descriptive context for the argument and parameter. The parameter name is used in the declaration of the method whereas the argument label is used when the method is called. By default, the argument label and parameter name are the same, but multiple parameters can have the same or unique argument label. The names of the parameters should be unique so that the compiler can easily distinguish them. We can also ignore the argument label by placing the underscore(_) before the name of the parameter. Syntax Following is the syntax for the argument label and parameter name − // Parameter name With argument label func methodname(argumentLabel parameterName: Type, parameterName: Type) -> returntype { Statement return value } methodname(name1:value, name2: value) // Parameter name without argument label func methodname(_name1: Type, _name2: Type) -> returntype { Statement return value } methodname(value1, value2) Example Swift program to demonstrate how to specify the parameter name and argument label in the method. // Defining class class CalculateSum { // Method with parameter name and argument label func addingTwoNumbers(num1 x:
Swift – Function vs Method
Swift – Function vs Method ”; Previous Next In Swift, functions and methods both are fundamental building blocks for optimizing and encapsulating code. It might be confusing to understand the difference between function and method, but we might think they are both the same. That”s not true. The methods are used in class, struct, and enum. They are called on the instances of that type and access and modify the properties of the instance. Whereas functions are defined independently or globally without creating a class or structure. Or we can say that a method is a function while a function is not a method. Swift Functions Functions are used to perform specific actions and are called by their names. It is very simple to pass the variables or constants as an argument while calling a function. Also, we can return a value from a function of any type. A function that works independently of a file can also be defined outside of it. Syntax Following is the syntax of a function − func functionName(parameters…) -> returnType { //Write statements here to perform actions } Example Swift program to demonstrate how to create and call a function. // Function without return value func show(msg: String) { print(“Welcome to, (msg)!”) } // Function call show(msg: “Tutorials Point”) // Function with return value func sumOfNumbers(_ nums: [Int]) -> Int { var sum = 0 // Calculating the sum of the numbers present in the array for n in nums { sum += n } return sum } // Function call with return value let inputNumbers = sumOfNumbers([3, 5, 6, 7, 1]) print(“Sum = (inputNumbers)”) Output It will produce the following output − Welcome to, Tutorials Point! Sum = 22 Swift Methods A method is a function and can be defined in classes, structures, and enumerations. Using methods, we can perform certain actions according to your requirements. As per our needs, we can define more than one method to perform different tasks. To access the defined methods in a class or structure we have to create an instance of the associated type. Using that object, we can call methods to perform tasks. Just like functions, we can also pass arguments while calling the method. Always remember that without creating an object of that class or struct we cannot access the methods. In the Swift language, there are two types of methods like the following − Instance Methods − As per their names, these are the instance-specific methods that can be called through the instances. The compiler will give us an error if we will try to access the methods without an instance of that class or struct. Also, we cannot call the methods of a class (for eg. Class Student) from another class”s instance. Type Methods − In Swift, we can define the type methods with prefix keywords like static or class. There is no need to create an instance of a class or struct to call type methods. They can be called directly from the type name. Syntax Following is the syntax of a method − func methodName(parameters…) -> returnType { //Write statements here to perform actions } Example Swift program to demonstrate how to create and call a method. // Defining a structure struct Student { // Properties let name: String let grade: Int // Instance method func displayInfo() { print(“name: (name)”) print(“grade: (grade)”) } // Type method static func dummyStudents() -> [Student] { return [Student(name: “Ray Sin”, grade: 4), Student(name: “Cherry Blossom”, grade: 2), Student(name: “Perry Scope”, grade: 7)] } } // Creating instance of the structure let anne = Student(name: “Anne Teak”, grade: 5) // Calling instance method from object anne anne.displayInfo() // Calling type method let students = Student.dummyStudents() print(“number of students: “, students.count) Output It will produce the following output − name: Anne Teak grade: 5 number of students: 3 Visual Identification Between Function and Method The Swift language shows how a function and method are denoted. It is visible that both are denoted as follows − The function has an icon like ƒ. The method has an icon of M. Difference Between Methods and Functions in Swift The following table will show the major difference between the methods and functions in Swift − Function Method The function is defined as independent. So that, we can define functions outside of the class. They are connected with a class or struct itself. Outside the scope, you can not define the methods. Functions are independent properties of structured languages like C/C++. Methods works within the scope of an object similar to Object-oriented languages like C#, Java, Swift, etc. Functions don”t capture any reference variables or constants. Methods are called using reference variables (or instances) only. While functions do not belong to classes, they perform individually. Methods are defined to manipulate the particular instance of that class or struct. No need to create objects to call them. An object is required to access them. Simply, every function is not a method. While every method is a function. Print Page Previous Next Advertisements ”;
Swift – Concurrency
Swift – Concurrency ”; Previous Next Concurrency provides the ability for Swift program to execute multiple tasks or operations simultaneously. Or we can say that it allows us to write asynchronous and parallel codes in a structured way. We are allowed to suspend and resume asynchronous code. Concurrency will improve the responsiveness and performance of the application. Asynchronous Functions In Swift, asynchronous functions or methods are the special type of functions or methods that can perform non-blocking and asynchronous operations. Such types of functions can be suspended in between their execution or they can also pause to wait for something. Also, we are allowed to mark the places where we want to suspend the execution of the function. To create a synchronous function or method we have to use the async keyword in the declaration part after the parameter list and before the return arrow. Syntax Following is the syntax for asynchronous function − func functionName(parameter) async -> returnType{ // statement } To suspend the execution of the asynchronous function or method until the awaited asynchronous operation completes, we have to use the await keyword in front of the call. It makes concurrent code easier to read. Following is the syntax for suspending the execution of asynchronous functions − await functionName(parameter) Asynchronous function or method can also throw an error and we can handle that error with the help of try and catch block. Following is the syntax for handling errors by asynchronous functions − func functionName() async throws -> Data { // asynchronous code that may throw an error } do { let data = try await functionName() // process data } catch { // handle error } We can also call asynchronous functions in parallel by using the async keyword in front of let while defining a constant and then writing the await keyword whenever we use the constant. Following is the syntax for calling asynchronous functions in parallel − // Calling asynchronous function in parallel async let result1 = functionName1(parameter) async let result2 = functionName2(parameter) // Suspend execution let suspendExecution = await[result1, result2] Example Swift program for asynchronous function. // Asynchronous function func randomFunc() async -> Int { Int.random(in: 10…40) } let result = await randomFunc() print(“Random Number:”, result) Output It will produce the following output − Random Number: 13 Task and Task Group In Swift, task and task groups are the main concepts that help us to work with asynchronous code in a structured manner. A task is a unit of work that can be executed concurrently. All the asynchronous codes that execute are part of the task. Generally, a task can perform one operation at a time but when we create multiple tasks then Swift will schedule them to run simultaneously. Whereas a task group is used to manage a collection of tasks and collectively perform operations on them. Here the tasks are arranged in a hierarchy, which means each task in the given group has the parent task and child tasks and this relationship is important because − While working with a parent task, you cannot forget to wait for its task to complete. If you set the priority of the child task to high then the priority of the parent task will automatically be set to high. If the parent task gets cancelled, then the child task will also cancelled. The local values of tasks can easily propagate to child tasks Task Cancellation We are allowed to cancel the execution of the task. Or we can terminate the ongoing task before it is completed. It is helpful in various cases like cleaning up resources and stopping long running operations. We can cancel the task with the help of the cancel() method provided by Swift. Example Swift program to create and cancel a task. import Foundation class MyTaskManager { private var task: DispatchWorkItem? func createTask() { // Create a DispatchWorkItem task = DispatchWorkItem { for i in 1…5 { if self.task?.isCancelled ?? false { print(“Task cancelled”) return } print(“Running task – (i)”) } print(“Task completed successfully”) } // Execute the task on a background queue DispatchQueue.global().async(execute: task!) } func cancelTask() { // Cancelling the task task?.cancel() } } let obj = MyTaskManager() // Create and run the task obj.createTask() // Wait for a while sleep(2) // Cancel the task obj.cancelTask() Output It will produce the following output − Running task – 1 Running task – 2 Running task – 3 Running task – 4 Running task – 5 Task completed successfully Actor As we know tasks are used to break our programs into isolated or concurrent pieces, which makes them run safely at the same time. And to add some information between these tasks Swift provides Actors. Actors are reference types and it allows only one task to access its mutable state at a time. That makes code run safely in multiple tasks and can easily interact with the same instance of an actor. In actor, if outside code tries to access the properties directly, then we will get an error. We can declare an actor with the help of the actor keyword. Also, we are allowed to create instances of actor just like class and structure to access the properties and methods of the actor. To suspend the execution of the actor we can use the await keyword. Syntax Following is the syntax for calling asynchronous functions in parallel − // Calling asynchronous function in parallel async let result1 = functionName1(parameter) async let result2 = functionName2(parameter) // Suspend execution let suspendExecution = await[result1, result2] Example
Swift – Deinitialization
Swift – Deinitialization ”; Previous Next Deinitialization is the process of releasing memory resources when an instance of the class is not required. Deinitializers work only with classes, not with the structure or enumeration. It is not necessary that Swift will immediately call a deinitializer when the instance is no longer needed, it will be called before the instance is deallocated and this timing is managed by the automatic reference counting(ARC) system. A class can have only one deinitializer. Deinitializers are automatically called developers are not allowed to call them manually The timing of calling the deinitializer is not explicitly controlled by the developer. It is automatically determined by the ARC. Circular references can prevent deinitialization. The deinitializer of the superclass is inherited by their subclasses and the deinitializer of the superclass is called after the implementation of the subclass deinitializer(even if the subclass does not have its own deinitializer). As we know the instance is not deallocated until after its deinitializer is called, so it means that the deinitialzer can access and modify the instance’s property. Defining Deinitializer in Class In Swift, we can define a deinitializer in a class using “deinit” keyword. The code present inside the deinitializer will execute when the instance of the class is deallocated. The Deinitializer does not take any parameter. Syntax Following is the syntax of the deinitializer class className{ // Properties and methods of class // Deinitializer deinit { // statement } } Example Swift program to create deinitializer. // Defining class class Student { // Property of class var name: String // Initializer to initialize instance init(name: String) { self.name = name print(“(name) is initialized”) } // Deinitializer to deinitialize instance deinit { print(“(name) is deinitialized”) } } // Creating and initializing instances of the student class var object1: Student? = Student(name: “Mira”) var object2: Student? = Student(name: “Jenni”) // Deinitializers will be called when instances are deallocated object1 = nil object2 = nil Output It will produce the following output − Mira is initialized Jenni is initialized Mira is deinitialized Jenni is deinitialized Deallocating Memory Space Using Deinitializer In Swift, deinitialization is handled by the Automatic Reference Counting(ARC). Automatic Reference Counting is a memory management mechanism that is used to keep track of the instance references and deallocate objects when they are no longer needed. Although Swift automatically deallocates memory resources we are not required to perform manual cleaning, but if we are using our resources, then we may have to clean them up manually. For example, if we create a custom class to open a file and write some data to it, we might need to close the file before the class instance is deallocated. Now, we will see how the deinitializer works − Step 1 − Create and initialize a new instance of the class using “init” initializer. Step 2 − Use the instance of the class with strong references. The instance of the class will stay alive as long as there is at least one strong reference to that object. Step 3 − When the last strong reference to an object is terminated at that time deinitializer will be automatically called by the ARC before the object is deallocated. Step 4 − Now the code present in the deinitializer is executed and the instance of the given class will be deallocated. The memory is free for other objects. So this is how deinitializer works. Example Swift program to demonstrate how deinitializer works. var counter = 0; // for reference counting class baseclass { init() { counter++; } deinit { counter–; } } var print: baseclass? = baseclass() print(counter) print = nil print(counter) Output It will produce the following output − 1 0 When print = nil statement is omitted the values of the counter remain the same since it is not deinitialized. Example var counter = 0; // for reference counting class baseclass { init() { counter++; } deinit { counter–; } } var print: baseclass? = baseclass() print(counter) print(counter) Output It will produce the following output − 1 1 Print Page Previous Next Advertisements ”;
Swift – Optional Chaining
Swift – Optional Chaining ”; Previous Next The process of querying, calling properties, subscripts and methods on an optional that may be ”nil” is defined as optional chaining. Optional chaining return two values − if the optional contains a ”value” then calling its related property, methods and subscripts returns values if the optional contains a ”nil” value all its its related property, methods and subscripts returns nil Since multiple queries to methods, properties and subscripts are grouped together failure to one chain will affect the entire chain and results in ”nil” value. Optional Chaining as an Alternative to Forced Unwrapping Optional chaining is specified after the optional value with ”?” to call a property, method or subscript when the optional value returns some values. Optional Chaining ”?” Access to methods,properties and subscriptsOptional Chaining ”!” to force Unwrapping. ? is placed after the optional value to call property, method or subscript. ! is placed after the optional value to call property, method or subscript to force unwrapping of value. Fails gracefully when the optional is ”nil”. Forced unwrapping triggers a run time error when the optional is ”nil”. Program for Optional Chaining with ”!” Example class ElectionPoll { var candidate: Pollbooth? } class Pollbooth { var name = “MP” } let cand = ElectionPoll() let candname = cand.candidate!.name Output When we run the above program using playground, we get the following result − main/main.swift:10: Fatal error: Unexpectedly found nil while unwrapping an Optional value Current stack trace: 0 libswiftCore.so 0x00007fd880a40dc0 _swift_stdlib_reportFatalErrorInFile + 112 1 libswiftCore.so 0x00007fd88070a191 <unavailable> + 1442193 2 libswiftCore.so 0x00007fd880709eb6 <unavailable> + 1441462 3 libswiftCore.so 0x00007fd880709caa <unavailable> + 1440938 4 libswiftCore.so 0x00007fd8807096d0 _assertionFailure(_:_:file:line:flags:) + 315 6 swift-frontend 0x000055a564ac0b3d <unavailable> + 26479421 7 swift-frontend 0x000055a563df4db9 <unavailable> + 13061561 8 swift-frontend 0x000055a563bc54c6 <unavailable> + 10769606 9 swift-frontend 0x000055a563bc19b6 <unavailable> + 10754486 10 swift-frontend 0x000055a563bc10a7 <unavailable> + 10752167 11 swift-frontend 0x000055a563bc341e <unavailable> + 10761246 12 swift-frontend 0x000055a563bc273d <unavailable> + 10757949 13 swift-frontend 0x000055a563a94a39 <unavailable> + 9521721 14 libc.so.6 0x00007fd880017d90 <unavailable> + 171408 15 libc.so.6 0x00007fd880017dc0 __libc_start_main + 128 16 swift-frontend 0x000055a563a94295 <unavailable> + 9519765 Stack dump: 0. Program arguments: /opt/swift/bin/swift-frontend -frontend -interpret main.swift -disable-objc-interop -color-diagnostics -new-driver-path /opt/swift/bin/swift-driver -empty-abi-descriptor -resource-dir /opt/swift/lib/swift -module-name main 1. Swift version 5.7.3 (swift-5.7.3-RELEASE) 2. Compiling with the current language version 3. While running user code “main.swift” Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it): /opt/swift/bin/swift-frontend(+0x551a103)[0x55a56869a103] /opt/swift/bin/swift-frontend(+0x551802e)[0x55a56869802e] /opt/swift/bin/swift-frontend(+0x551a48a)[0x55a56869a48a] /lib/x86_64-linux-gnu/libc.so.6(+0x42520)[0x7fd880030520] /opt/swift/lib/swift/linux/libswiftCore.so(+0x160195)[0x7fd88070a195] /opt/swift/lib/swift/linux/libswiftCore.so(+0x15feb6)[0x7fd880709eb6] /opt/swift/lib/swift/linux/libswiftCore.so(+0x15fcaa)[0x7fd880709caa] /opt/swift/lib/swift/linux/libswiftCore.so($ss17_assertionFailure__4file4line5flagss5NeverOs12StaticStringV_A2HSus6UInt32VtF+0x13b)[0x7fd88070980b] [0x7fd87ece717e] /opt/swift/bin/swift-frontend(+0x1940b3d)[0x55a564ac0b3d] /opt/swift/bin/swift-frontend(+0xc74db9)[0x55a563df4db9] /opt/swift/bin/swift-frontend(+0xa454c6)[0x55a563bc54c6] /opt/swift/bin/swift-frontend(+0xa419b6)[0x55a563bc19b6] /opt/swift/bin/swift-frontend(+0xa410a7)[0x55a563bc10a7] /opt/swift/bin/swift-frontend(+0xa4341e)[0x55a563bc341e] /opt/swift/bin/swift-frontend(+0xa4273d)[0x55a563bc273d] /opt/swift/bin/swift-frontend(+0x914a39)[0x55a563a94a39] /lib/x86_64-linux-gnu/libc.so.6(+0x29d90)[0x7fd880017d90] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x80)[0x7fd880017e40] /opt/swift/bin/swift-frontend(+0x914295)[0x55a563a94295] Illegal instruction (core dumped) The above program declares ”election poll” as class name and contains ”candidate” as membership function. The subclass is declared as ”poll booth” and ”name” as its membership function which is initialized as ”MP”. The call to the super class is initialized by creating an instance ”cand” with optional ”!”. Since the values are not declared in its base class, ”nil” value is stored thereby returning a fatal error by the force unwrapping procedure. Program for Optional Chaining with ”?” Example class ElectionPoll { var candidate: Pollbooth? } class Pollbooth { var name = “MP” } let cand = ElectionPoll() if let candname = cand.candidate?.name { print(“Candidate name is (candname)”) } else { print(“Candidate name cannot be retreived”) } Output When we run the above program using playground, we get the following result − Candidate name cannot be retreived The program above declares ”election poll” as class name and contains ”candidate” as membership function. The subclass is declared as ”poll booth” and ”name” as its membership function which is initialized as ”MP”. The call to the super class is initialized by creating an instance ”cand” with optional ”?”. Since the values are not declared in its base class ”nil” value is stored and printed in the console by the else handler block. Defining Model Classes for Optional Chaining & Accessing Properties Swift 4 language also provides the concept of optional chaining, to declare more than one subclasses as model classes. This concept will be very useful to define complex models and to access the properties, methods and subscripts sub properties. Example class rectangle { var print: circle? } class circle { var area = [radius]() var cprint: Int { return area.count } subscript(i: Int) -> radius { get { return area[i] } set { area[i] = newValue } } func circleprint() { print(“The number of rooms is (cprint)”) } var rectarea: circumference? } class radius { let radiusname: String init(radiusname: String) { self.radiusname = radiusname } } class circumference { var circumName: String? var circumNumber: String? var street: String? func buildingIdentifier() -> String? { if circumName != nil { return circumName } else if circumNumber != nil { return circumNumber } else { return nil } } } let rectname = rectangle() if let rectarea = rectname.print?.cprint { print(“Area of rectangle is (rectarea)”) } else { print(“Rectangle Area is not specified”) } Output When we run the above program using playground, we get the following result − Rectangle Area is not specified Calling Methods Through Optional Chaining Example class rectangle { var print: circle? } class circle { var area = [radius]() var cprint: Int { return area.count } subscript(i: Int) -> radius { get { return area[i] } set { area[i] = newValue } } func circleprint() { print(“Area of Circle is: (cprint)”) } var rectarea: circumference? } class radius { let radiusname: String init(radiusname: String) { self.radiusname = radiusname } } class circumference { var circumName: String? var circumNumber: String? var circumarea: String? func buildingIdentifier() -> String? { if circumName !=
Swift-Overriding
Swift – Overriding ”; Previous Next Overriding is a very common concept in object-oriented programming languages. Using overriding we are allowed to re-implement a method or property of a superclass in a subclass. It allows us to extend the behaviour of inheritance. While overriding the method or property we are providing a new implementation in the subclass instead of using the the implementation in the superclass. In Swift, we can override the method or the property of the superclass. Access to Superclass Methods, Properties and Subscripts The ”super” keyword is used as a prefix to access the methods, properties and subscripts declared in the superclass. Overriding Access to methods, properties and subscripts Methods super.somemethod() Properties super.someProperty() Subscripts super[someIndex] Rules for overriding in Swift Following are some rules you should follow while overriding − The overridden method or property in the subclass must have the same signature(name, parameter and return type) as they are in the superclass. Use the super keyword to call the overridden implementation from the superclass in the overriding method. Use the override keyword to override properties. We can override both stored and computed properties. The access level of an overriding method or property cannot be more restrictive than the access level of the overridden method or property in the base class. You are not allowed to override a public method with a private method. So always check the access modifier before overriding. Methods Overriding in Swift In Swift, we are allowed to override methods. The overriding method means a subclass can provide a different implementation for a method that is already defined in the base class. Or we can say that we can customize the behaviour of a superclass method in the subclass. The overridden method in the subclass must have the same signature(name, parameter and return type) as the base class and the compiler will determine which method is called according to the type of object. Also, the access level of the overridden method in the subclass must be the same or more permissive than the access level of the method in the superclass. The override method is defined by using the override keyword in the subclass. This keyword is placed before starting the function definition. It tells the compiler that the method will override the method of the superclass. If we do not specify the override keyword then the compiler will give us the error. Syntax Following is the syntax for method overriding − override func methodName(Parameters) -> returntype { Statement return parameters } Example Swift program for method overriding. // Super class class cricket { // Method func show() { print(“Welcome to Swift Super Class”) } } // Sub class class tennis: cricket { // Overriden Method override func show() { print(“Welcome to Swift Sub Class”) } } // Creating instance of subclass let tennisinstance = tennis() // Accessing the override method tennisinstance.show() Output It will produce the following output − Welcome to Swift Sub Class Property Overriding Swift supports property overriding. Just like method overriding, property overriding also provides a way for a subclass to customize the implementation of the properties that are already defined in the base class. We can say that using property overriding, we can provide our own getter and setter for that property or add property observers, which enables the overriding property to observe when the property value changes. The type of the overridden property in the subclass must have the same name and type as the property in the base class. So that the compiler will determine which property(either the superclass property or overridden property) is called according to the type of object. The access level of the overridden method in the subclass must be similar or more permissive than the access level of the property in the superclass. The override property is defined by using the override keyword in the subclass. This keyword is placed before starting the property definition. It tells the compiler that the property will override the property of the superclass. If we do not specify the override keyword, then the compiler will give us the error. Syntax Following is the syntax for property overriding − override var propertyName: type{ // Statement } Example Swift program for property overriding. // Superclass class mySuperClass { // Property var language: String{ return “C++” } } // Subclass class mySubClass: mySuperClass { // Override Property override var language: String{ return “Swift” } } // Creating an instance of a subclass let obj = mySubClass() // Accessing the overridden property print(obj.language) Output It will produce the following output − Swift Overriding Property Getters and Setters Swift allows the user to override the getter and setter of the subclass property, whether the property is stored or computed. The name and the type of the overriding property must be the same as the property present in the base case. So that the compiler knows that you are overriding the property of the base class. In Swift, we are allowed to represent the read-only inherited property as a read-write property by providing both a getter and setter in the subclass while overriding. Whereas we are not allowed to represent the read-write-only inherited property as read-only property. When setter is defined for overriding property the user has to define getter too. If we do not wish to modify the value of the inherited property in the overriding getter, then we can pass the inherited value using ”super.PropertyName” from the getter, where PropertyName represents the name of the overriding property. Example Swift