【问题标题】:Why can a public type throw an error that is a private type?为什么公共类型会抛出私有类型的错误?
【发布时间】:2018-11-09 23:17:47
【问题描述】:

为什么这段代码会编译?

// ===============
// MyStruct.swift
// ===============    

private enum MyError: Error {
    case unexpectedError
}    

public struct MyStruct {
    static func throwError() throws {
        throw MyError.unexpectedError
    }
}    

// ===============
// main.swift
// ===============    

do {
    try MyStruct.throwError()
}
catch {
    print(error) // "unexpectedError"
}

documentation on access control 非常清楚,我们不能在公共类型成员中返回私有类型:

函数的访问级别不能高于其参数类型和返回类型

前面的语句对我来说似乎很明显,下面的示例显示了它如何无法编译(我们现在返回它而不是抛出它):

private enum MyError: Error {
    case unexpectedError
}    

public struct MyStruct {

    // Note: we are now returning `MyError` instead of throwing
    static func returnError() -> MyError { // Error: Method must be declared fileprivate because its result uses a private type
        return MyError.unexpectedError
    }
}

对我来说似乎并不明显且文档中未提及的是为什么我们可以在公共类型 (@987654325 @)。

【问题讨论】:

  • 我会发表评论,因为我不太了解底层细节,但在投掷的情况下,MyError 不会公开暴露。您不能使用catch MyError.unexpectedError,因为它不是公开的。由于所有throws 暴露都是Error,所以没有问题。但是对于 return,您正在明确尝试公开 MyError 类型。

标签: swift private public access-control


【解决方案1】:

你可以很容易地返回私有类型的东西

private enum MyError : Error {
  case unexpectedError
}

public struct MyStruct {
  static func myError() -> Error {
    return MyError.unexpectedError
  }
}

...通过将其隐藏为非私有类型的值。这只是子类型。或者:unexpectedErrorMyError 类型,但它也是Error。你不能暴露 type MyError,但是你可以用它的值做任何你想做的事情,只要你不告诉任何人比“这些是Errors”更具体的事情.

同样,您可以轻松地抛出私有类型的东西

public struct MyStruct {
  static func throwError() throws {
    throw MyError.unexpectedError
  }
}

因为throw 想要Error,所以你给它一个MyErrorMyError : Errorthrows 注释本身并没有说明 throwError throwing MyErrors;它只是说它通常可能会抛出Errors。

【讨论】:

  • 睡觉后才意识到这一点,太明显了!谢谢!您的解释简单明了。
猜你喜欢
  • 2016-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-08
  • 2014-01-03
  • 1970-01-01
  • 2020-08-06
  • 1970-01-01
相关资源
最近更新 更多