2017-05-01 9 views
1

より多くのプロトコル指向プログラミングアプローチを達成するために、クラスの代わりに構造体を使用する場合、私は少しのアクセス制御の問題を抱えています。プロトコル拡張:get-onlyプロパティに割り当てることができません

私はネットワーク経由でさまざまなメッセージタイプを受け取りました。これらのメッセージタイプは、生の形式で単純にバイトの配列です。

私はプロトコルから始めます。私は、スレッドセーフであると、すべての値型のプロトコル指向の良さを使用しようとしている

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

:発信者が直接生のバイトを操作することはできませんのでrawBytesだけ{ get }としてマークされているか注意Swift、クラスの代わりに構造体を使用して異なるメッセージタイプを作成し、プロトコルを採用しました。

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

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

すべて異なるメッセージタイプは、例えば、最初の10バイトのための類似の構造を共有する:

  • バイト[0] = permissionsByte
  • バイト[1] = connectionTypeByte
  • など...

私は構造体を使用しているので、継承はありません。しかし、メッセージタイプ間で同様の振る舞いを持つためにはまだ何らかの方法が必要です。 OK、プロトコル拡張を使用します:

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... 

} 
+1

'生の形は単純にバイトの配列です。いいえ、それらはデータではありません。 'Data'を使用してください。 – Alexander

答えて

0

を開くする必要がありますするつもりです同じファイル内に定義されている場合は、privateの代わりにfileprivateを使用してください。

fileprivateは、同じファイルのコードにアクセスできますが、ファイルの外にはアクセスできません。

は、参照してください - https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AccessControl.html

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] 
} 
+0

興味深い!私がこれを見る唯一の問題は、今では単一のソースファイルに詰まっていることです。これらのリクエストタイプの中には、数多くのコード行を扱う膨大な辞書があります。つまり、バイト[9] = 100のときは "Hello"、バイト[9] = 101の場合は "さよなら"など。 – MH175

+0

@ MH175これはSwift 4で修正されます。 'private'は同じモジュール内の拡張モジュールへのアクセスを拡張しますhttps://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction- between-private-declarations-and-extensions.md – Alexander

+0

同じソースファイル内で、同じモジュール内ではありません。 –

関連する問題