Почему открытый тип может выдавать ошибку закрытого типа? - PullRequest
0 голосов
/ 31 мая 2018

Почему этот код компилируется?

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

Что мне не кажется очевидным и не упоминается в документации, то почему мы можем throw этот закрытый тип (MyError) в методе открытого типа (MyStruct).

1 Ответ

0 голосов
/ 31 мая 2018

Вы можете легко вернуть что-то закрытого типа

private enum MyError : Error {
  case unexpectedError
}

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

..., скрыв его как значение не очень закрытого типа.Это просто подтип.Или: unexpectedError имеет тип MyError, но это также и Error.Вы не можете выставить тип MyError, но вы можете делать с его значениями все, что захотите, если вы не скажете никому ничего более конкретного, чем «это Error s».

Точно так же вы можете легко бросить что-то личного типа

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

, потому что throw хочет Error, вы даете ему MyError и MyError : Error.Сама аннотация throws ничего не говорит о throwError метании MyError с;он просто говорит, что может выбросить Error с в целом.

...