Swift协议只能设置?

Art*_*onk 34 protocols getter-setter ios swift

为什么我可以做到这一点没有任何错误:

var testDto = ModelDto(modelId: 1)
testDto.objectId = 2
Run Code Online (Sandbox Code Playgroud)

虽然我定义了这个:

protocol DataTransferObject {
    var objectType: DtoType { get }
    var parentObjectId: Int { get set }
    var objectId: Int { get }
    var objectName: String { get set }
}

struct ModelDto: DataTransferObject {
    var objectType: DtoType
    var parentObjectId: Int
    var objectId: Int
    var objectName: String

    init(modelId: Int) {
        self.objectType = DtoType.Model
        self.objectId = modelId
        self.parentObjectId = -1
        self.objectName = String()
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我的协议中的定义大部分被忽略(getter,setter定义),为什么我还要使用它们呢?

Ima*_*tit 48

Apple声称"Swift编程语言(Swift 3)":

如果协议只要求属性可以获取,那么任何类型的属性都可以满足要求,如果这对您自己的代码有用,则该属性也可以设置.

因此,以下五个Playground代码段都是有效的:

示例#1:常量属性

protocol FullyNamed {
    var fullName: String { get }
}

struct Duck: FullyNamed {
    let fullName: String
}

let scrooge = Duck(fullName: "Scrooge McDuck")
print(scrooge.fullName) // returns "Scrooge McDuck"
Run Code Online (Sandbox Code Playgroud)

示例#2:变量属性

protocol FullyNamed {
    var fullName: String { get }
}

struct Duck: FullyNamed {
    var fullName: String        
}    

var scrooge = Duck(fullName: "Scrooge McDuck")
print(scrooge.fullName) // returns "Scrooge McDuck"

scrooge.fullName = "Scrooge H. McDuck"
print(scrooge.fullName) // returns "Scrooge H. McDuck"
Run Code Online (Sandbox Code Playgroud)

示例#3:计算属性(仅限获取)

protocol FullyNamed {
    var fullName: String { get }
}

struct Duck: FullyNamed {
    private var name: String
    var fullName: String {
        return name
    }
}

let scrooge = Duck(name: "Scrooge McDuck")
print(scrooge.fullName) // returns "Scrooge McDuck"
Run Code Online (Sandbox Code Playgroud)

示例#4:计算属性(获取和设置)

protocol FullyNamed {
    var fullName: String { get }
}

struct Duck: FullyNamed {
    private var name: String
    var fullName: String {
        get {
            return name
        }
        set {
            name = newValue
        }
    }
}

var scrooge = Duck(name: "Scrooge McDuck")
print(scrooge.fullName) // returns "Scrooge McDuck"

scrooge.fullName = "Scrooge H. McDuck"
print(scrooge.fullName) // returns "Scrooge H. McDuck"
Run Code Online (Sandbox Code Playgroud)

示例#5:private(set)变量属性

/* Duck.swift located in Sources folder */

protocol FullyNamed {
    var fullName: String { get }
}

public struct Duck: FullyNamed {
    public private(set) var fullName: String

    public init(fullName: String) {
        self.fullName = fullName
    }

    public mutating func renameWith(fullName: String) {
        self.fullName = fullName
    }
}

/* Playground file */

var scrooge = Duck(fullName: "Scrooge McDuck")
print(scrooge.fullName) // returns "Scrooge McDuck"

scrooge.renameWith("Scrooge H. McDuck")
print(scrooge.fullName) // returns "Scrooge H. McDuck"
Run Code Online (Sandbox Code Playgroud)

Apple还声明:

如果协议要求属性可获取和可设置,则不能通过常量存储属性或只读计算属性来满足该属性要求.

出于这个原因,以下两个游乐场代码片段有效:

示例#1:常量属性

protocol FullyNamed {
    var fullName: String { get set }
}

struct Duck: FullyNamed {
    let fullName: String
}

let scrooge = Duck(fullName: "Scrooge McDuck")
// Error message: Type 'Duck' does not conform to protocol 'FullyNamed'
Run Code Online (Sandbox Code Playgroud)

示例#2:计算属性(仅限获取)

protocol FullyNamed {
    var fullName: String { get set }
}

struct Duck: FullyNamed {
    private var name: String
    var fullName: String {
        return name
    }
}

var scrooge = Duck(name: "Scrooge McDuck")
// Error message: Type 'Duck' does not conform to protocol 'FullyNamed'
Run Code Online (Sandbox Code Playgroud)

示例#3:计算属性(仅限获取)

protocol FullyNamed {
    var fullName: String { get }
}

struct Duck: FullyNamed {
    var fullName: String {return "Scrooge McDuck"}

    init(fullName: String) {
        self.fullName = fullName 
  // Error Message Cannot assign to Property: "FullName" is get only
    }
}
Run Code Online (Sandbox Code Playgroud)


Ank*_*oel 25

根据官方文件:

getter和setter要求可以通过各种方式的符合类型来满足.如果属性声明包含get和set关键字,则符合类型可以使用存储的变量属性或可读写的计算属性(即实现getter和setter的计算属性)来实现它.但是,该属性声明不能实现为常量属性或只读计算属性.如果属性声明仅包含get关键字,则可以将其实现为任何类型的属性.

  • 奇怪的斯威夫特!获取和设置意味着可获得和可设置一个只获取意味着做你想要的吗?:) (3认同)
  • 即使我不觉得这很奇怪.这是协议的作用.他们定义了必须实施的规则.{get}说符合要求的东西必须有一个吸气剂.它可能有也可能没有二传手. (3认同)
  • @ArturPajonk,我在这种行为中看不出任何奇怪的东西.你的struct`ModelDto`确实有`objectId`的getter和setter.它符合`DataTransferObject`协议,通过使用getter,但只要你直接使用`ModelDto`,它就会暴露一个setter.所以你可以随意打电话.如果你希望隐藏你的setter,你可以将`ModelDto`转换为`DataTransferObject` (2认同)