Search code examples
swiftinheritance

Swift: How to make a overriden function that's not available for call


I would like to create a function that must be overriden by subclass, but that function is not available for use. For example.

open class Animal {
  func favFood() throws -> String {
    throw UnImplementedError()
  }

  func eatFood() throws {
    print("Yum, I love \(try favFood())")
  }
}

class Cat: Animal {
  override func favFood() throws -> String {
    return "fish"
  }
}

let cat = Cat()
try cat.eatFood()  // I want this method to be available
try cat.favFood()  // I want to prevent people from using this method

I saw a solution that uses fileprivate. But in my case, it doesn't make logical sense to keep all the overriden method in the same file. I also want to allow any module to override the Animal, but force them to implement the favFood()

Allowing a function to be accessed/overriden by subclass but not any other class in same module in swift

I guess, one possible sol'n is to create an initializer in the Animal class to force the subclass to pass the "favFood" as a parameter. But, that could get messy if I have many functions that need to be overriden. Or the method must be called after the object is created.


Solution

  • Although not a perfect solution, I think you can do this with @available(*, unavailable). So my example above with the Cat class, it would change to:

    class Cat: Animal {
      @available(*, unavailable)
      override func favFood() throws -> String {
        return "fish"
      }
    }
    

    This means that the responsibility falls on the subclass to prevent it from being used, but it's better than nothing.