InterviewSolution
This section includes InterviewSolutions, each offering curated multiple-choice questions to sharpen your knowledge and support exam preparation. Choose a topic below to get started.
| 1. |
class A { var name:String init(name:String) { self.name = name } } class B:A { var id : String init(name:String, id : String){ self.id = id super.init(name: name) } convenience init (id:String) { super.init(name: "unknown") self.id = id } } |
|
Answer» Key is to use associated types, which is a powerful way of making protocols generic. protocol Store { associatedtype DataType var ids: [DataType] { get set} mutating func add(id: DataType) } EXTENSION Store { mutating func add(id: DataType) { ids.append(id) } } struct SystemOne: Store { var ids = [STRING]() } struct SystemTwo: Store { var ids = [INT]() } var sysOne = SystemOne() sysOne.add(id: "ONE") sysOne.add(id: "Two") var sysTwo = SystemTwo() sysTwo.add(id: 1) sysTwo.add(id: 2) print(sysOne.ids) print(sysTwo.ids) |
|
| 2. |
Please look at the code segment below. If we compile it what happens? Explain |
|
Answer» Use dependency injection to redesign the classes and PROVIDE data from test METHODS protocol IBookStorage { func fetchAllBooks()->[Book] } class BookStorage: IBookStorage { func fetchAllBooks() -> [Book] { // return all available books } } class BooksManager { let bookStorage:IBookStorage INIT(bookStorage:IBookStorage) { self.bookStorage = bookStorage } func physicsBooks() -> [Book] { let books = bookStorage.fetchAllBooks() // identify the physics book and return those let physicsbooks = … return physicsbooks } } class StubBookStorage: IBookStorage { var books = [Book]() init(books:[Book]) { self.books = books } func fetchAllBooks() -> [Book] { return books } } // Test methods func testBookManager() { let books = … // add STUB data you want to test let bookStorage = StubBookStorage(books: books) let bookManager = BooksManager(bookStorage: bookStorage) let physicsBooks = bookManager.physicsBooks() // test the value physicsBooks array if correct } |
|
| 3. |
What is the exact difference in the view model in MVVM and controller in MVC? Which pattern is preferable keeping in mind the code unit test coverage? |
Answer»
Explanation: employee3 is a struct, and we ASSIGN employees2 = employees separate array in memory is CREATED in the memory. And when we add emp3 in employees it is not reflected in employees2. But emp1 and emp2 are reference TYPES. So if we change employees[0].name = "Sam Smith" employees2[0] is also changed as they refer to the same OBJECT. |
|
| 4. |
Consider a scenario where I have two different system storage which requires IDs in different data types. One system will deal int values only and others in string values only. Create a generic protocol with a single property “ids” ( holds an array of ids) and a function to add id, that will be used for two systems. |
|
Answer» DUMP function is used to print the content of the object For eg: class PERSON { let name: String let cars: [String]? init(name:String, cars: [String]?) { self.name = name self.cars = cars } }let allPerson = [Person(name: "P1", cars: ["P1_C1", "P1_C2"]), Person(name: "P2", cars: ["P2_C1", "P2_C2"])] Output: ▿ 2 elements ▿ App.Person #0 - name: "P1" ▿ cars: Optional(["P1_C1", "P1_C2"]) ▿ some: 2 elements - "P1_C1" - "P1_C2" ▿ App.Person #1 - name: "P2" ▿ cars: Optional(["P2_C1", "P2_C2"]) ▿ some: 2 elements - "P2_C1" - "P2_C2" //As seen, dump() OUTPUTS the whole class hierarchy, while print() SIMPLY outputs the class name. |
|
| 5. |
We want to test cover the function of physicsBooks. Test the logic if it identifies the physics books from different data sets. Redesign this classes to test cover the method. |
|
Answer» There will be a compilation error. The derived class Car calls the init method of superclass before its stored property, model gets INITIALISED. Swift does 2 phase initialization, in first phase memory is ALLOCATED and all stored properties get initialized starting from the derived classes and then its superclass. Then in the second phase, all customizations of the properties are done, in the init method. The correct code will be : class Car:TRANSPORT { VAR model:STRING init(model:String){ self.model = model super.init(type: "Car") self.model = "\(self.model) - type \(self.type)" print("\(self.model)") } } The result will be Transport - Car Maruti - type Car |
|
| 6. |
enum BookType { case biology case physics case maths case unknown } class Book { var name:String? var type:BookType = .unknown } class BookStorage { func fetchAllBooks() -> [Book] { // return all available books } } class BooksManager { func physicsBooks() -> [Book] { let books = BookStorage().fetchAllBooks() // identify the physics book and return those let physicsbooks … return physicsbooks } } |
|
Answer» It WOULD provide a compilation error as emp1 == emp2 cannot be RESOLVED by compiler. It depends if the structs/classes are ADAPTED to the Hashable protocol. The primitive data TYPE like Int, String by default implement the Hashable protocol, show they do not show any error if we compare instances of such data types. The corrected code would be: struct Employee: Hashable { var name:String var id:Int init(name:String, id:Int) { self.name = name self.id = id } var hashValue: Int { return self.id} } The printed result would be true. |
|
| 7. |
Please consider the following code: (Advanced) |
|
Answer» The derived CLASS convenience initializers only and call convenience initializer or DESIGNATED initializer of own class. Ultimately the call chain should have designated initializer at last of the same class. So the CORRECT code is : class A { var name:STRING init(name:String) { self.name = name } } class B:A { var id : String init(name:String, id : String){ self.id = id super.init(name: name) } convenience init (id:String) { self.init(name: "unknown", id: id) } } |
|
| 8. |
class Employee4 { var name:String var id:Int init(name:String, id:Int) { self.name = name self.id = id } } func testAssignment() { let emp1 = Employee4(name: "Sam", id: 1) let emp2 = Employee4(name: "John", id: 2) let emp3 = Employee4(name: "Robert", id: 3) var employees = [emp1,emp2] let employees2 = employees employees[0].name = "Sam Smith" employees.append(emp3) for emp in employees2 { print("name \(emp.name)") } } |
|
Answer» In MVC, CONTROLLER is coordinated that reads / saves data into the data model and displays data / handles actions in the view. In MVVM, the view model is a CLOSE representation of a view. The view model is bound to the view. Any change in data in the view model, leads to notifiications and view pulls data from the view model and it displays it. Test covering controllers can be a bit DIFFICULT as view is tightly attached to a view i.e View controller will have an instance of a view within it. So it will be difficult to mock the view methods called from the controller. Test covering in ViewModel is RATHER easy as it does not contain any REFERENCE to a view. Rather it only prepares data for the view only. It is the view that pulls the data from the view model. Also, the view delegates the action to the View model. |
|
| 9. |
Please look at the code below. If we run method ., what will be the output and why? |
|
Answer» Key is to use associated types, which is a powerful way of making protocols generic. protocol STORE { associatedtype DataType VAR ids: [DataType] { get set} mutating func add(id: DataType) } extension Store { mutating func add(id: DataType) { ids.append(id) } } STRUCT SystemOne: Store { var ids = [String]() } struct SystemTwo: Store { var ids = [INT]() } var sysOne = SystemOne() sysOne.add(id: "One") sysOne.add(id: "Two") var sysTwo = SystemTwo() sysTwo.add(id: 1) sysTwo.add(id: 2) print(sysOne.ids) print(sysTwo.ids) |
|
| 10. |
What is the use of the dump function? Explain with example. |
|
Answer» Use DEPENDENCY injection to redesign the classes and provide data from test methods protocol IBookStorage { func fetchAllBooks()->[Book] } class BookStorage: IBookStorage { func fetchAllBooks() -> [Book] { // return all available books } } class BooksManager { let bookStorage:IBookStorage init(bookStorage:IBookStorage) { self.bookStorage = bookStorage } func physicsBooks() -> [Book] { let books = bookStorage.fetchAllBooks() // identify the physics book and return those let physicsbooks = … return physicsbooks } } class StubBookStorage: IBookStorage { VAR books = [Book]() init(books:[Book]) { self.books = books } func fetchAllBooks() -> [Book] { return books } } // Test methods func testBookManager() { let books = … // add stub data you want to test let bookStorage = StubBookStorage(books: books) let bookManager = BooksManager(bookStorage: bookStorage) let physicsBooks = bookManager.physicsBooks() // test the value physicsBooks array if CORRECT } |
|
| 11. |
class Transport { var type:String init(type:String) { self.type = type print("Transport - \(type)") } } class Car:Transport { var model:String init(model:String){ super.init(type: "Car") self.model = model self.model = "\(self.model) - type \(self.type)" print("\(self.model)") } } If we try to execute the following what will be the result. Provide reasons let car = Car(model:”Maruti”) |
Answer»
Explanation: employee3 is a struct, and we assign employees2 = employees separate array in MEMORY is CREATED in the memory. And when we add emp3 in employees it is not reflected in employees2. But emp1 and emp2 are REFERENCE types. So if we change employees[0].name = "Sam Smith" employees2[0] is also CHANGED as they REFER to the same object. |
|
| 12. |
Consider the following code snippet |
|
Answer» DUMP function is used to print the content of the object For eg: class Person { let name: STRING let cars: [String]? init(name:String, cars: [String]?) { self.name = name self.cars = cars } }let allPerson = [Person(name: "P1", cars: ["P1_C1", "P1_C2"]), Person(name: "P2", cars: ["P2_C1", "P2_C2"])] Output: ▿ 2 elements ▿ App.Person #0 - name: "P1" ▿ cars: Optional(["P1_C1", "P1_C2"]) ▿ some: 2 elements - "P1_C1" - "P1_C2" ▿ App.Person #1 - name: "P2" ▿ cars: Optional(["P2_C1", "P2_C2"]) ▿ some: 2 elements - "P2_C1" - "P2_C2" //As seen, dump() OUTPUTS the whole class hierarchy, while print() simply outputs the class name. |
|
| 13. |
class SwiftBasics { static func test() { let emp1 = Employee(name: "John", id: 10) let emp2 = Employee(name: "John", id: 10) print("\(emp1 == emp2)") } } struct Employee { var name:String var id:Int init(name:String, id:Int) { self.name = name self.id = id } } |
|
Answer» There will be a compilation error. The derived class Car calls the init method of superclass before its stored property, model gets INITIALISED. SWIFT does 2 phase INITIALIZATION, in first phase memory is allocated and all stored properties get initialized starting from the derived classes and then its superclass. Then in the SECOND phase, all customizations of the properties are done, in the init method. The correct code will be : class Car:Transport { var model:String init(model:String){ self.model = model super.init(type: "Car") self.model = "\(self.model) - type \(self.type)" print("\(self.model)") } } The RESULT will be Transport - Car Maruti - type Car |
|
| 14. |
In the code below when what will happen if we compile and execute SwiftBasics. test() method. Provide reasons. |
|
Answer» It would provide a COMPILATION error as emp1 == emp2 cannot be RESOLVED by compiler. It depends if the structs/classes are adapted to the Hashable protocol. The primitive data type like Int, String by default implement the Hashable protocol, SHOW they do not show any error if we compare instances of such data types. The corrected code would be: struct EMPLOYEE: Hashable { var name:String var id:Int init(name:String, id:Int) { self.name = name self.id = id } var hashValue: Int { RETURN self.id} } The printed result would be true. |
|