Swift позволяет перегрузить универсальные методы с помощью ограничений, наложенных на переданные универсальные типы.
Да ... но очень ясно, что это статическая перегрузка , а не динамическое переопределение . Он основан на типах, которые могут быть проверены во время компиляции.
func delegatingMethod<T>(_ value: T) {
baseMethod(value)
}
Мы сейчас компилируем это, и нам нужно записать это как конкретный статический вызов функции, возможно встроенный, в двоичный файл. Что мы знаем о T
? ничего не знаем о T
, поэтому любое предложение where
завершится неудачей.
Мы даже не знаем, как вызывается эта функция, потому что вызов может исходить из другого модуля или модуля компиляции. Хотя в принципе он может иметь различную семантику в зависимости от уровня доступа, например, если одна версия используется, когда она является закрытой, и все вызовы могут быть оценены, а другая используется, когда она общедоступна, это будет действительно ужасным источником ошибок.
То, что вы запрашиваете, - это delegatingMethod
отложить свое решение о том, какой вызов функции сделать до времени выполнения. Это не то, как работают дженерики. Более того, вы просите, чтобы все предложения where
были закодированы где-то в двоичном файле, чтобы их можно было оценить во время выполнения. Также не как работают дженерики. Это потребует гораздо более динамичной системы диспетчеризации, чем Swift хочет реализовать. Это не невозможно; это просто совершенно другое животное, и оно предотвращает множество оптимизаций.
Такое ощущение, что вы пытаетесь заново изобрести наследование классов с помощью протоколов и обобщений. Ты не можешь Это разные решения и разные функции. Классовое наследование является фундаментально динамичным. Протоколы и дженерики в основном статичны. Если вы хотите динамическую диспетчеризацию на основе определенных типов, используйте классы.