W1401 Object Oriented Design

From Coder Merlin
Revision as of 05:21, 14 November 2020 by Chukwuemeka-tinashe (talk | contribs)
Within these castle walls be forged Mavens of Computer Science ...
— Merlin, The Coder

Introduction[edit]

Object Oriented Design is the problem solving approach in programming paradigm where object oriented approach is followed. In simple words object oriented designing is the way of breaking down distinct aspects of a problem into modules called objects and developing a solution by making those objects interact with each other by sending messages or information. This approach is adopted by many programming languages, not only Swift, but also in Java, Java Script, C#, C++, Python, Ruby etc. and dates back to 1950s. While being so, object oriented designing of programming and algorithms have been considered as one of the most efficient ways of problem solving in programming domain while other major paradigm is structured programming approach. While structures programming is considered task-centric, object oriented design is known to be data-centric.

In Object oriented designs, the objects are used to model different components of the problem which ranges from the physical things like a book, a touch on a screen, a database to more complex representations of abstraction like the daily petrol price, fluctuation of rate of interest etc.

Definition of Object[edit]

Object is the encapsulated representation of an entity which combines the data and the associated procedure. The rules and binding ways are formulated in object interface following which the interaction of the objects takes place. Before grasping the advanced and real life usage of objects, for basic familiarity and easy understanding, its better to start with the physical things like taking it literally.

Generally, in object oriented designs, the objects are designed to describe a set of general concepts and then extending to more specific types. Start with the concept of Musical instrument. After defining Musical instrument as an object, you can create (in abstraction) the extended concept of Musical instrument in form of particular instances like Piano, Viola, Violin, Guitar, Electric Guitar etc. which are more specific kinds but can be derived from the same parent object.

Going DeeperGoingDeeperIcon.png
  • The usage of the word 'object' in programming paradigm has its genesis back in late 1950 within the group of Scientists working for Artificial Intelligence based on LISP programming Language at MIT.

Initializing Object in Swift[edit]

Properties[edit]

// Example of declaration of class
class Instrument{
  // 2
  let brand: string
  // 3
  init(brand: string) {
    //4 
    self.brand = brand
  }
}

In this example, we have declared the base object as Instrument. The object has been declared and defined with the key word class. It is customary to use capitalization while defining the base objects. While it is not mandatory to always capitalize the base class, but it is general convention which is followed. While defining the object Instrument, some property should be defined which will be common for all the instances that we will derive from this object in future viz. piano, guitar, electric guitar etc. Here the property of 'brand' has been declared and defined as the string type. With this definition process the initialization of object 'Instrument' was successfully carried out.

Encapsulation[edit]

Methods[edit]

After defining property to the object, the behavior should be added which is done via adding methods.

func tune() -> String {
  fatalError("Implement this method for \(brand)")
}

The tune() method is a placeholder function which can cause crashes when called. Methods like this are often called as abstract since they are very generic and not intended for direct usage. Rather than merely calling the function fatalError(), it is expected to create a subclass of such method to override the method in order to do something sensible or more specific. Functions that are defined under a class are said as methods since they have the access to the corresponding property. Here, the tuning method has the access to the property brand. This way of organizing the properties and associated functions together is the basis why object oriented designing has been successful in tackling highly complex problems. Such combining practice of property and associated function is called Encapsulation. In other words, class types are known to encapsulate the data (stored properties) and behavior (methods).

class Music {
  let notes: [String]

  init(notes: [String]) {
    self.notes = notes
  }

  func prepared() -> String {
    return notes.joined(separator: " ")
  }
}
func play(_ music: Music) -> String {
  return music.prepared()
}

With creating the new class Playmusic, it will be possible to accept different strings of array as the input and the string output in flatten form with the help of the prepared() method. Also, the play() function allows us the have the String which needs to be played. Its always better to create a class of Music than just to pass an array of strings as by this class, the function calling and the properties remain organized and it also gives the scope to expand this class as per need in future.

func perform(_ music: Music) {
  print(tune())
  print(play(music))
}

The perform(_:) method is a a composite method which combined the two methods namely the tune() method and the play() method in order to tune and play at the same time.

Inheritance[edit]

By definition, in Object Oriented Design, inheritance is the way of going from general to more specific, in other words from class to subclass.

// 1
class Piano: Instrument {
  let hasPedals: Bool
  // 2
  static let whiteKeys = 52
  static let blackKeys = 36
  
  // 3
  init(brand: String, hasPedals: Bool = false) {
    self.hasPedals = hasPedals
    // 4
    super.init(brand: brand)
  }
  
  // 5
  override func tune() -> String {
    return "Piano standard tuning for \(brand)."
  }
  
  override func play(_ music: Music) -> String {
    // 6 
    let preparedNotes = super.play(music)
    return "Piano playing \(preparedNotes)"
  }
}

Here, as the Piano object has been initialized as the subclass of parent class Instrument, all the properties and methods got inherited in to the child class Piano. From the real life situation, since all the pianos irrespective of their make should always have exactly the same number of black and white keys, the declaration of the corresponding property has been made static.

With the help of initializer, the default value of the parameter hasPedals is determined, which also has the option to keep it off. The Super keyword is used to call the parent class which is Instrument and it is done after determination of child class property hasPedals. With the use of super class initializer we are able to initialize the inherited property, which in this case is brand.

Method Override[edit]

By keyword overriding, the inherited tune() method's implementation is overridden. By doing so, we are successfully able to make tune() execute something specific to Piano while not simply calling fatalError(). The method play(_:)is also overridden here. The Instrument parent method is called here with the usage of Super keyword so that the prepared notes can be obtained and then it can be played. Since Piano is subclass of Instrument, it can be presumed without any error that it has brand as its property and the corresponding methods (behaviors) as tune(), play() and perform().

Hint.pngHelpful Hint

The initialization process used by Swift classes are always two-phase-initialization in order to ensure that all the properties are initialized before using them.

Interfaces[edit]

Information hiding[edit]

Polymorphism[edit]

Exercises[edit]

References[edit]