Если я правильно понял ваш вопрос, может быть, это хорошо поможет.
вы можете дать bark() реализацию по умолчанию, расширив протокол. Затем в других классах, соответствующих протоколу, вы можете изменить реализацию функции коры:
protocol Bark {
func bark()
}
//default implementation
extension Bark {
func bark() { print("Bark") }
}
class Dog: Bark {}
//By calling bark func in Poodle, you change the default implementation.
class Poodle: Dog {
func bark() { print("Yap") }
}
class GermanShephard: Dog {
func bark() { print("Woof") }
}
let dog = Dog()
let poodle = Poodle()
let germanShephard = GermanShephard()
dog.bark()
//Bark
poodle.bark()
//Yap
germanShephard.bark()
//Woof
Вы также можете не делать какую-либо реализацию по умолчанию, а просто добавлять свою для каждой ситуации.
Изменить после комментария:
Это одна из основных причин, по которой протоколы полезны. Они устраняют тесную связь, связанную с созданием подклассов. Это базовый пример, так как вся тема содержит много информации, но вместо создания подкласса Dog вы можете сделать протокол DogRepresentable и назначить все свойства и функции по умолчанию, которые все собаки реализуют одинаково. Затем вы можете расширить DogRepresentable, где self: UIViewController и реализовать функциональность по умолчанию:
protocol Barkable {
func bark()
}
protocol DogRepresentable: Barkable {
//properties and functions all dogs will have with same implementation
}
extension DogRepresentable where Self: UIViewController {
//default implementation for functions all dogs will use
}
Назначая Barkable классу DogRepresentable, вы знаете, что любой класс, соответствующий DogRepresentable, также должен соответствовать Barkable.
Теперь, когда вы назначаете DogRepresentable классу, он получит всю реализацию по умолчанию, которую получит базовый класс, и вам придется вызывать функцию bark(), чтобы правильно соответствовать протоколу:
class Dog: DogRepresentable {
func bark() { print("Bark") }
}
class Poodle: DogRepresentable {
func bark() { print("Yap") }
}
class GermanShephard: DogRepresentable {
//Won't conform because it doesn't have bark()
}
Таким образом, вы получите всю реализацию по умолчанию, такую как базовый класс, но не забудете переопределить функцию суперкласса.
Изменить 2 на основе второго комментария:
В этом случае вам лучше всего оставить DogRepresentable без соответствия Barkable, а затем создать протоколы для разных типов: поэтому, если у вас есть собаки, которые тявкают, вы можете сделать протокол Yappable, который имеет функцию лая и реализацию по умолчанию. Тогда у вас может быть другой протокол Barkable с собственной функцией лая и собственной реализацией по умолчанию. Затем пусть класс соответствует тому протоколу, которому он должен соответствовать. Пудель соответствует Yappable, Собака соответствует Barkable.
Создавая эти отдельные протоколы, вы можете хранить функциональность для каждой ситуации в одном месте и использовать только тот, который вам нужен, сохраняя ваш код более чистым, читабельным и СУХИМ.
person
JustinM
schedule
15.12.2016