首页 > 解决方案 > 为什么公共类型会抛出私有类型的错误?

问题描述

为什么这段代码会编译?

// ===============
// 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"
}

关于访问控制的文档非常清楚,我们不能在公共类型成员中返回私有类型:

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

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

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

对我来说似乎并不明显并且文档中没有提到的是,为什么我们可以将这个私有类型 ( )扔到MyError公共类型 ( MyStruct) 的方法中。

标签: swiftprivatepublicaccess-control

解决方案


您可以轻松地返回私有类型的东西

private enum MyError : Error {
  case unexpectedError
}

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

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

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

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

因为throw想要一个Error,你给它一个MyError,和MyError : Error。注释本身并throws没有说明throwErrorthrowing MyErrors; 它只是说它通常可能会抛出Errors。


推荐阅读