Swift协议扩展`var {get}`覆盖实现的`let`

时间:2016-05-26 02:14:35

标签: swift override protocols protocol-extension

当将实现结构分配给键入为var的变量时,使用letprotocol实现属性的行为会有所不同。

protocol Req {
  var path: String? { get }
}
extension Req {
  var path: String? { return "Req" }
}

struct LetReq: Req {
  let path = "LetReq"
}
struct VarReq: Req {
  var path: String? { return "VarReq" }
}

var req: Req!

req = VarReq()
req.path // prints "VarReq"

req = LetReq()
req.path // prints "Req" not "LetReq" which seems very awkward.

这是Swift设计的行为吗?

3 个答案:

答案 0 :(得分:1)

我认为这是一个编译错误。如果您将LetReq作为可选字符串,它将按预期工作:

struct LetReq: Req {
    let path: String? = "LetReq"
}

File a bug与Apple合作。

答案 1 :(得分:0)

我认为这种行为是正确的。

struct LetReq: Req {
    let path = "LetReq"
}

路径String类型不是String?

var req: Req!
req = LetReq()
req.path

reqReq的类型。因此,req.path表示类型为String?,名称为path

Req的扩展程序具有path变量的默认变量。因此req.path引用的变量不是LetReq的{​​{1}}

答案 2 :(得分:0)

它含糊不清......但我会赌一个错误。

至少对于当前的实施(<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <script type="text/javascript"> $(document).ready(function() { var crudServiceBaseUrl = "http://localhost:49885/api", dataSource = new kendo.data.DataSource({ transport: { read: { url: crudServiceBaseUrl + "/Suppliers", dataType: "json", type: "Get" }, update: { url: function(data) { debugger; //return crudServiceBaseUrl + "/Suppliers/" + JSON.stringify(data.models[0]); return crudServiceBaseUrl + "/Suppliers"; }, dataType: "json", type: "Put", contentType: "application/json" }, destroy: { url: function(data) { debugger; return crudServiceBaseUrl + "/Suppliers/" + JSON.stringify(data.SupplierId); //return crudServiceBaseUrl + "/Suppliers"; }, //url: crudServiceBaseUrl + "/Suppliers", dataType: "json", type: "Delete", contentType: "application/json" }, create: { url: function (data) { debugger; //return crudServiceBaseUrl + "/Suppliers/" + JSON.stringify(data); return crudServiceBaseUrl + "/Suppliers"; }, //url: crudServiceBaseUrl + "/Suppliers", dataType: "json", type: "Post", contentType: "application/json", //data: JSON.stringify([data.SupplierId, data.CommId]) }, parameterMap: function(options, operation) { debugger; if (operation !== "read" && options) { return { models: JSON.stringify(options) }; } } }, batch: false, pageSize: 20, schema: { data: function(data) { //specify the array that contains the data return data || []; }, errors: function(response) { return response.error; }, model: { id: "SupplierId", fields: { SupplierId: { validation: { required: true } }, CommId: { validation: { required: true } }, EmailId: { validation: { required: true } }, FullName: { validation: { required: true } }, FirstName: { validation: { required: true } }, Description: { validation: { required: true } }, LastName: { validation: { required: true } }, StateId: { validation: { required: true } } } } } }); $("#grid").kendoGrid({ dataSource: dataSource, navigatable: true, pageable: true, sortable: true, height: 550, toolbar: ["create", "save", "cancel"], columns: [ "SupplierId", { field: "SupplierId", title: "SupplierId", width: 120 }, { field: "CommId", title: "CommId", width: 120 }, { field: "EmailId", title: "EmailId", width: 120 }, { field: "FullName", width: 120 }, { field: "FirstName", width: 120 }, { field: "Description", width: 120 }, { field: "LastName", width: 120 }, { field: "StateId", width: 120 }, { command: "destroy", title: "&nbsp;", width: 150 } ], editable: true }); }); </script> <div id="example"> <div id="grid"></div> </div> 2.2);

  1. Swift仅支持不同返回类型的方法重载。
  2. 但仅限于方法,而不是属性。
  3. 因此,所有属性都必须具有不同的名称。
  4. 这可以通过这证明。

    swiftc

    但无论如何,编译器似乎没有通过协议扩展来检查这种重新声明。因此,struct AA { func a() -> String { return "" } func a() -> String? { return "" } var b: String { return "" } var b: String? { return "" } // Error: Invalid redeclaraion of `b`. } 实例实际上提供了两个属性。

    LetReq

    你可以用这个来检查。

    var path: String { get }
    var path: String? { get }
    

    我相信编译器必须防止这种属性重载。出于同样的原因,他们在print(LetReq().path as String?) // prints `Optional("Req")`. print(LetReq().path as String) // prints `LetReq`. 中阻止了财产超载。所以,我认为这是一个错误。