Search code examples
oopswiftinformation-hiding

Information Hiding the "Swifter" way?


I have a question regarding object oriented design principles and Swift. I am pretty familiar with Java and I am currently taking a udacity course to get a first hands on in Swift.

In the Java community (basically in every community that follows OOP) it is very common to use information hiding techniques such as hiding or encapsulating data within classes to make sure it cannot be manipulated from outside. A common principle is to declare all attributes of a class as being private and use getters for retrieving an attribute's value and setters for manipulation.

I tried to follow this approach when writing a class that was part of the course and it looks like this:

//
//  RecordedAudio.swift
//  Pitch Perfect
//

import Foundation

class RecordedAudio: NSObject {
    private let filePathUrl: NSURL!
    private let title: String?

    init(filePathUrl: NSURL, title: String?)
    {
        self.filePathUrl = filePathUrl
        self.title = title
    }

    func getFilePathUrl() -> NSURL
    {
        return filePathUrl
    }

    func getTitle() -> String
    {
        if title != nil
        {
            return title!
        }
        else
        {
            return "none"
        }
    }
}

The code works and my private attributes cannot be accessed from outside my class, which is exactly the behavior I wanted to achieve. However, the following questions came to my mind:

1.) The course instructor decided to leave the attributes' access control level at the default "internal" and not use getters/setters but rather access the attributes directly from outside. Any thoughts on why developers might do that in swift? Is my approach not "swift" enough???

2.) In conclusion: Is there a "swifter" way to implement encapsulation when writing your own class? What are swift's native techniques to achieve the information hiding I am aiming for?


Solution

  • You can restrict external property manipulation, by marking the property public for reading and private for writing, as described in the documentation:

    class RecordedAudio: NSObject {
    
        public private(set) let filePathUrl: NSURL!
        public private(set) let title: String?
    
        init(filePathUrl: NSURL, title: String?) {
            self.filePathUrl = filePathUrl
            self.title = title
        }
    
    }
    
    // in another file
    
    let audio = RecordedAudio(filePathUrl: myUrl, title: myTitle)
    
    let url = audio.filePathUrl // works, returns the url
    audio.filePathUrl = newUrl // doesn't compile