Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift - mixing abstract and concrete methods

Swift has no abstract classes and methods. Instead, it offers protocols.

That's fine when your classes are either fully abstract or fully concrete.

But what is the best 'Swift' way to implement an abstract class that also has concrete methods?

Pseudo-code example:

class Animal {
  abstract makeSound()
  abstract eyeCount()
}

class Mammal : Animal {
  override eyeCount { return 2 } // Let's assume all mammals have hard-coded 2 eyes...

class Cat : Mammal {
  override makeSound { print "Meow!" }
}

class Dog : Mammal {
  override makeSound { print "Woof!" }
}

In Mammal, I do want to implement the concrete method eyeCount() because all mammals have 2 hard-coded eyes (supposedly) and I don't want to re-implement it in dog and cat. However, makeSound() should only be implemented for Dog and Cat as mammals have varying voices.

How would you implement this in Swift? Thanks!

like image 243
Hatchmaster J Avatar asked Jun 01 '15 13:06

Hatchmaster J


People also ask

Can abstract class have both concrete and abstract methods?

Abstract class can have both an abstract as well as concrete methods. A concrete class can only have concrete methods. Even a single abstract method makes the class abstract. Abstract class can not be instantiated using new keyword.

Can concrete methods be on abstract classes?

Abstract Classes Compared to Interfaces You cannot instantiate them, and they may contain a mix of methods declared with or without an implementation. However, with abstract classes, you can declare fields that are not static and final, and define public, protected, and private concrete methods.

Can a concrete method call an abstract method?

Yes, this is allowed. A subclass can override a concrete method and declare it abstract. Of course, because this subclass contains an abstract method, the subclass itself must also be declared abstract. You would then need a further (concrete) subclass to implement the method to be able to instantiate an object.

Does Swift support abstraction?

Swift does not support abstraction like other language. Interface and abstraction both can achieve by Protocol. Abstraction is useful when you want to define method for common classes. For example if multiple classes is there, and they are using similar method.


2 Answers

I would implement it like this:

class AbstractAnimal
{
    // Fully abstract method
    func methodThatReturnsSomething() -> String  {
        fatalError("methodThatReturnsSomething() is abstract and must be overriden!");
    }

    func eyeCount() -> Int {
        return 2;
    }
}

fatalError prevents Xcode from complaining that abstract method methodThatReturnsSomething() doesn't actually return anything.

like image 96
BadmintonCat Avatar answered Sep 24 '22 02:09

BadmintonCat


You can use Protocol Extensions to get the exact same behavior as with Abstract Classes: Checking if abstract methods are implemented in subclasses at compile time.

protocol Entity {
  // MARK: - Abstract methods
  func filename() -> String

  // MARK: - Traits
  func saveData(data: NSArray)
}

extension Entity {
  func saveData(data: NSArray) {
      // Do something and call:
      let filename = filename()
  }
}

Now you can implement the Entity protocol on a Subclass and the compiler will force you to implement filename() while the saveData() method is already implemented.

like image 41
pommes Avatar answered Sep 24 '22 02:09

pommes