Какая реализация logMessage() сработает в каждом из двух вызовов? Что будет в консоли и почему?
protocolLogger{}extensionLogger{funclogMessage(){print("Logging from base logger.")}}structFeatureLogger:Logger{funclogMessage(){print("Logging from feature.")}}let featureLogger =FeatureLogger()let logger:Logger= featureLogger
featureLogger.logMessage()logger.logMessage()
Дополнительные вопросы
1. Можно ли изменить код так, чтобы два раза вывелось Logging from feature?
Темы
Компании
Ответ
featureLogger.logMessage()// Logging from feature.logger.logMessage()// Logging from base logger.
Сначала рассмотрим структуру и вызов ее метода.
structFeatureLogger:Logger{funclogMessage(){print("Logging from feature.")}}let featureLogger =FeatureLogger()featureLogger.logMessage()
Хоть структура и соответствует протоколу Logger, вызов идет не через тип протокола. Поэтому используется статическая диспетчеризация. Компилятор уже знает, какую реализацию вызвать, и программа делает прямой вызов метода структуры.
print выведет: Logging from feature.
Теперь рассмотрим часть с протоколом.
protocolLogger{}extensionLogger{funclogMessage(){print("Logging from base logger.")}}let logger:Logger= featureLogger
logger.logMessage()
Вызов метода уже идет через тип протокола. Казалось бы, диспетчеризация должна быть через witness table. Но посмотрим внимательнее.
Функция logMessage() объявлена в extension к протоколу, но не объявлена в самом протоколе. Это не требование протокола, поэтому метод не попадет в witness table.
Значит, при этом вызове будет статическая диспетчеризация: logMessage() через тип протокола выполнит базовую реализацию из extension.
print выведет: Logging from base logger.
Дополнительные вопросы
1. Чтобы в обоих случаях вывелось Logging from feature., второй вызов нужно перевести на динамическую диспетчеризацию через witness table. Для этого достаточно добавить logMessage() в требования протокола. Тогда вызов через тип протокола возьмет реализацию структуры, т.к. метод у FeatureLogger уже есть, и он попадет в таблицу.
protocolLogger{funclogMessage()}featureLogger.logMessage()// Logging from feature.logger.logMessage()// Logging from feature.