Как определить переменную, которую можно установить и получить в расширении протокола - PullRequest
0 голосов
/ 04 октября 2018

Я родом из мира Java.Сейчас я программирую на Swift 4.

Я бы хотел реализовать абстрактный класс в Swift, я знаю, что в Swift нет такого понятия абстрактного класса.Но я знаю, что мы могли бы подражать этой концепции в Swift, используя протокол.Например, вот что я попробовал:

// With protocol, I can define functions that concrete class have to implement
protocol ProductProvider {
   func getProductNumber() -> Int
}

// with protocol extension, I can define shared (computed) properties and functions among concrete classes that comply with this protocol
extension ProductProvider {
  var maxProductCount: Int {
        return 10
  }
}

Но теперь я хотел бы иметь общую переменную, которую можно было бы установить и получить («общая» означает, что она будет использоваться совместно с классами, которые соответствуют этому протоколу):

extension ProductProvider {
  var maxProductCount: Int {
        set(newValue) {
           // set to what if I couldn't define private stored variable in extension to hold the most recent set value ?
        }
        get{
           // how to return the most recent value set?
        }
  }
}

Мой вопрос в комментарии приведенного выше кода.Как я могу сделать этот набор и получить переменную в расширении протокола в Swift 4?Если это невозможно, какие обходные пути возможны?

Ответы [ 2 ]

0 голосов
/ 06 октября 2018

Я думаю, что самый простой способ - определить переменную в протоколе с помощью метода get и set.Затем в вашем объекте соответствия вы должны объявить переменную для соответствия.Пример:

protocol AbstractObject {

    var maxProductCount: Int { get set }
}

struct ConformObject: AbstractObject {

    var maxProductCount: Int
}

Так что теперь вы можете использовать вашу переменную в реализациях по умолчанию

extension AbstractObject {

    mutating func addOne() -> Int {
        self.maxProductCount += 1
        return 1
    }
} 
0 голосов
/ 04 октября 2018

Помимо обсуждения, если это правильный способ достичь того, что вы хотите, вы можете использовать ассоциацию объектов.

public final class ObjectAssociation<T: AnyObject> {

    private let policy: objc_AssociationPolicy

    /// - Parameter policy: An association policy that will be used when linking objects.
    public init(policy: objc_AssociationPolicy = .OBJC_ASSOCIATION_RETAIN_NONATOMIC) {

        self.policy = policy
    }

    /// Accesses associated object.
    /// - Parameter index: An object whose associated object is to be accessed.
    public subscript(index: AnyObject) -> T? {

        get { return objc_getAssociatedObject(index, Unmanaged.passUnretained(self).toOpaque()) as! T? }
        set { objc_setAssociatedObject(index, Unmanaged.passUnretained(self).toOpaque(), newValue, policy) }
    }
}

И в вашем расширении

extension SomeType {

    private static let association = ObjectAssociation<NSObject>()

    var simulatedProperty: NSObject? {

        get { return SomeType.association[self] }
        set { SomeType.association[self] = newValue }
    }
}

Это невозможнохранить типы Swift напрямую через объектную ассоциацию.Вы можете хранить, например, NSNumber вместо Int.
Источник: https://stackoverflow.com/a/43056053/1811810

...