简体   繁体   English

如何在Swift中专门化泛型枚举

[英]How to specialize a generic enum in Swift

I'm using the antitypical/result package to provide a generic Result type. 我正在使用典型/结果包来提供通用的Result类型。 This package defines Result as follows: 该程序包定义结果如下:

public enum Result<T, Error> {
     ...
}

Now, I only wish to return errors of type NSError in my code, so it would be nice if I didn't have to keep doing things this: 现在,我只希望在我的代码中返回类型为NSError错误,所以如果我不必继续这样做,那就太好了:

func myFunc() -> Result<String, NSError> { ... }

Instead, I want to create a derived StdResult type so that I can do this instead: 相反,我想创建一个派生的StdResult类型,以便可以代替这样做:

func myFunc() -> StdResult<String> { ... }

I've tried various things but I can't find a solution. 我已经尝试过各种方法,但是找不到解决方案。 This, for example, doesn't work: 例如,这不起作用:

typealias StdResult<T> = Result<T, NSError>

Is there a solution which will work? 有没有可行的解决方案?

Unfortunately we're pretty limited here. 不幸的是,我们在这里非常有限。 Swift doesn't support generic typealias, so we can do this as a sort of hack with struct: Swift不支持通用的typealias,因此我们可以通过struct来实现:

struct StdResult<T> {
    typealias Type = Test<T, NSError>
}

func myFunc() -> StdResult<String>.Type {

}

Does that fit what you were looking for closely enough? 这是否足以满足您的需求?

At the moment, there's no generic typealias support nor enumeration inheritance, but you could use RawRepresentable protocol. 目前,没有通用的类型别名支持或枚举继承,但是您可以使用RawRepresentable协议。 It's not as easy as if a generic typealias exists, but it may fit your needs. 这并不像存在通用类型别名那样容易,但是它可能满足您的需求。

RawRepresentable 原始代表

From Apple's documentation : 苹果的文档

A type that can be converted to an associated "raw" type, then converted back to produce an instance equivalent to the original. 可以转换为关联的“原始”类型,然后再转换回以生成与原始等效的实例的类型。

public protocol RawRepresentable {
  typealias RawValue
  public init?(rawValue: Self.RawValue)
  public var rawValue: Self.RawValue { get }
}

That said, your raw value must be Result<T, NSError> : 也就是说,您的原始值必须为Result<T, NSError>

enum StdResult<T>: RawRepresentable {

  var rawValue: Result<T, NSError> {
    switch self {
    case .Success(let value):
      return Result.Success(value)
    case .Failure(let error):
      return Result.Failure(error)
    }
  }

  init?(rawValue: Result<T, NSError>) {
    switch rawValue {
    case .Success(let value):
      self = .Success(value)
    case .Failure(let error):
      self = .Failure(error)
    }
  }

  case Success(T)
  case Failure(NSError)
}

func myFunc() -> StdResult<String> { }

Note : Properties and methods of original Result enumeration are only accessible from rawValue property, so, for example, if you want to compare your new StdResult with another, you must use rawValue property or reimplement these protocols yourself. 注意只能rawValue属性访问原始Result枚举的属性和方法,因此,例如,如果要将新的StdResult与另一个进行比较,则必须使用rawValue属性或自己重新实现这些协议。

You could alias the specific Result type so you don't have to constantly do func myThing() -> Result<String, NSError> 您可以为特定的Result类型添加别名,这样就不必经常执行func myThing() -> Result<String, NSError>

eg 例如

typealias StringResult = Result<String, NSError>

func myOtherThing() -> StringResult

It's more difficult for me to come up with a generic solution like 对我来说,想出一个通用的解决方案比较困难

MyResult<String>

without understanding exactly what Result is doing. 不了解Result到底在做什么。 I could take another crack at it if you post some of the internals. 如果您发布一些内部信息,我可能会再三破解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM