使用Self作为泛型类型

14

Self 可以用作方法的返回类型:

func doSomething() -> Self {}

是否可以像这样将Self用作通用类型?

func doSomething() -> Wrapper<Self> {}

例子

如果我可以对ChristmasPresent进行子类化,并让它具有一个wrapped函数,该函数返回一个WrappedPresent,其中泛型设置为子类的任何内容,那将是很好的。

class ChristmasPresent {
    func wrapped() -> WrappedPresent<Self> {
        return WrappedPresent(present: self)
    }
}

class WrappedPresent<T: ChristmasPresent> {
    var present: T

    init(present: T) {
        self.present = present
    }
}

class ToyCar: ChristmasPresent {}

let wrappedToyCar = ToyCar().wrapped() // Inferred to be: WrappedPresent<ToyCar> 

这个约束表示什么?这个通用约束在哪里注册?Wrapper是如何声明的?如果它是Wrapper<T:class>,我们可以返回Wrapper<self.dynamicType>,也许... - cmyr
你不知道“Self”类型的原因是什么呢?也许我没有想得够深入。你可以随时用实际的类名替换“Self”。 - bjtitus
我已经添加了一个例子 :)。 - Rengers
@Rengers 我可能错了,但我有一种感觉,我的问题与这里的问题有关:https://dev59.com/VoXca4cB1Zd3GeqPNs-f。泛型并不像你期望的那样处理类和子类。这可能是因为它们被设计成完成它们实际上完成的结构和协议的工作。 - matt
这里有一个有趣的侧面。我可以让Swift生成一个错误消息“'Self'仅在协议中可用或作为类方法的结果。”但它也可以作为实例方法的结果 - 虽然也许这里的“类方法”意味着“类的方法”,而不是与“实例方法”相对的“类方法”。我想我会就此提交一个错误报告。 - matt
1个回答

21
在Swift中最令人困惑的悖论是:“Swift更喜欢方法,但Swift的函数更强大。” Swift团队知道这一点,我相信总有一天我们会拥有强大的方法。但今天不是那一天。你想在方法中表达的许多事情是无法实现的。然而,你想要的一切都可以轻松地用函数来完成。
class ChristmasPresent {}

struct WrappedPresent<T: ChristmasPresent> {
    let present: T
}

func wrap<T:ChristmasPresent>(present: T) -> WrappedPresent<T> {
    return WrappedPresent(present: present);
}

class ToyCar: ChristmasPresent {}

let wrappedToyCar = wrap(ToyCar()) // Inferred to be: WrappedPresent<ToyCar>

请注意,如果您的代码已经编译通过,结果可能仍然会让您感到惊讶。Swift自定义类型不是协变的,因此WrappedPresent<ToyCar>不是WrappedPresent<ChristmasPresent>的子类型。因此,如果您有一个包裹礼物的数组,您不能把一个包裹着玩具车的礼物放进去。这很容易迫使您回到使用固定(非类型参数化)的WrappedPresent类型,从而使问题无关紧要。在Swift中,泛型和类并不总是像您想象的那样混合。
如果您有一个实际的问题示例需要解决,请务必在开发论坛上提出。Swift团队非常负责任。

1
当然,我从没想过这可以用函数来解决!还是太过于沉浸在Objective-C的思维模式中 :)。 - Rengers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接