协议扩展:无法分配给get-only属性

时间:2017-05-01 04:02:59

标签: swift protocol-extension

当使用结构代替类来实现更加面向协议的编程方法时,我遇到了一些访问控制难题。

我通过网络接收不同的消息类型,它们的原始形式只是一个字节数组。

所以我从一个协议开始。 请注意rawBytes仅标记为 { get } ,以便调用者无法直接操作原始字节:

protocol NetworkDataRequest {
     var rawBytes: [UInt8] { get }
}

我试图保持线程安全并使用Swift的所有值类型,面向协议的优点,所以我现在使用结构而不是类创建不同的消息类型,并采用协议。

struct FileRequest: NetworkDataRequest {
     private(set) var rawBytes: [UInt8]
}

struct ConnectionRequest: NetworkDataRequest {
     private(set) var rawBytes: [UInt8]
}

所有不同的消息类型共享前10个字节的类似结构,例如:

  • byte [0] = permissionsByte
  • byte [1] = connectionTypeByte
  • 等...

因为我使用结构,所以我没有继承权。但我仍然需要一些方法在消息类型之间有类似的行为。好的,我使用协议扩展名:

 extension NetworkDataRequest {

      var permissionsByte: UInt8 {
          get { return bytes[0] }
          set { bytes[0] = newValue } //<-- Nope!
      }

 }

但是哎呀! rawBytes无法访问:

Cannot assign through subscript: 'rawBytes' is a get-only property

这有什么办法吗?否则我的所有结构都将有很多样板代码(对我来说很糟糕),或者我将不得不打开rawBytes(非常糟糕)

struct FileRequest: NetworkDataRequest {

     private(set) var rawBytes: [UInt8]

      var permissionsByte: UInt8 {
          get { return bytes[0] }
          set { bytes[0] = newValue }
      }


      var connectionTypeByte: UInt8 {
          get { return bytes[1] }
          set { bytes[1] = newValue } 
      }

      ///etc...

}

2 个答案:

答案 0 :(得分:1)

这样的事情怎么样?

public protocol NetworkDataRequest {
     var rawBytes: [UInt8] { get }
}

private protocol NetworkDataRequestPrivate: NetworkDataRequest {
     var rawBytes: [UInt8] { get set }
}

extension NetworkDataRequest {
    var permissionsByte: UInt8 {
        get { return rawBytes[0] }
    }
}

extension NetworkDataRequestPrivate {
    var permissionsByte: UInt8 {
        get { return (self as NetworkDataRequest).permissionsByte }
        set { rawBytes[0] = newValue }
    }
}

public struct FileRequest: NetworkDataRequestPrivate {
    fileprivate(set) public var rawBytes: [UInt8]
}

public struct ConnectionRequest: NetworkDataRequestPrivate {
    fileprivate(set) public var rawBytes: [UInt8]
}

答案 1 :(得分:0)

如果协议和协议扩展名在同一文件中定义,则使用fileprivate代替private

fileprivate允许来自同一文件的代码访问它,但在文件之外它是不可访问的。

参考 - https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AccessControl.html