Вызов свойств класса из расширения протокола - PullRequest
1 голос
/ 28 октября 2019

При использовании расширения протокола для реализации по умолчанию я сталкиваюсь с проблемой. Я определяю протокол с различными необязательными свойствами и функциями для использования. В расширении я реализую функцию по умолчанию и свойства nil. В реализации я использую свойства и функции из протокола.

На устройстве это работает так, как я ожидаю. Также в отладчике он дал мне свойство из класса, когда я столкнулся с точкой останова в реализации расширения.

Может кто-нибудь помочь мне, почему я не получил свойство в примере из класса, но нольсобственность от расширения.

Пример с детской площадки

import UIKit

protocol Collectable {

    var item: String?  { get }
    func collect()
}

extension Collectable {
    var item: String?  { return nil }
    func collect() {
        if let some = item {
            print("collect \(some)")
        } else {
            print("nothing")
        }
    }
}

class Car: Collectable {
    var item = "letter"
}

let car = Car()
car.collect()

Ответы [ 2 ]

2 голосов
/ 28 октября 2019

В протоколе ваш элемент является необязательной строкой, в то время как в вашем классе вы объявили еще одну переменную с именем item. Ваша функция сбора ищет необязательный элемент, и в расширении вы указали, что он должен вернуть nil.

1 голос
/ 28 октября 2019

Как сказал @SavcaMarin в своем ответе, у вас есть конфликт типов между свойством item, объявленным в вашем расширении (String?), и свойством в Car (String).

Вы можете увидеть это, если прокомментируете расширение. Компилятор скажет вам, что Car не соответствует Collectable. Если вы попросите его создать необходимые заглушки, он создаст func collect и var item: String?. Затем он выдает ошибку, что item переопределен.

Как Роб и Мэтт указали в комментариях на другой ответ, это, похоже, ошибка в компиляторе Swift. Это не указывает на переопределение item или несоответствие вашего item протоколу, если есть реализация по умолчанию, которая удовлетворяет требованиям протокола (ваше расширение).

Простоеисправление заключается в том, чтобы сообщить Swift, что item в Car - это то же самое, что и элемент в Collectable, объявив тип явно (String?), а не полагаясь на вывод типа (который дает String):

class Car: Collectable {    
    var item:String? = "letter"
}
...