Функция Swift generi c ограничена классом generic - PullRequest
0 голосов
/ 21 апреля 2020

Рассмотрим следующий код:

public class Test<P: AnyObject> {
    public func foo<T: P>(_ t: T.Type) -> T { // ERROR: Type 'T' constrained to non-protocol, non-class type 'P'
        // stuff happens
    }
}

Обратите внимание на ошибку во второй строке, утверждая, что P не является типом класса. Однако в строке 1 P объявлено как расширение AnyObject, и, следовательно, ДОЛЖНО быть типом класса. Поэтому ошибка неверна. ...Правильно? Что случилось с этим кодом и / или компилятором?


Редактировать: вот пример с пятью подобными обобщенными c функциями. Каждый из них сравнивается с функциональностью, которую я хочу, и любые комментарии в верхнем регистре отмечают способы, которыми они не отвечают моим желаниям. Чтобы сделать пример немного более конкретным, я заменил AnyObject на конкретный класс C0. Обратите внимание, что C2 подклассы C1 подклассы C0 и что CX не имеет отношения.

public class C0 {
    public required init() {
    }
}

public class C1: C0 {
    public required init() {
    }
}

public class C2: C1 {
    public required init() {
    }
}

public class CX {
    public required init() {
    }
}

//public class D0<P: AnyObject> { // AnyObject replaced with C0 for a more concrete example
public class D0<P: C0> {
    public func foo0<T: P>(_ t: T.Type) -> T { // DOESN'T COMPILE
        return t.init()
    }
    public static func test_foo0() {
//      let c2_0: C2 = D0<C1>().foo0(C2.self) // Function sig doesn't compile; can't test
//      let cX_0: CX = D0<C1>().foo0(CX.self) // Function sig doesn't compile; can't test
    }



    // Shadows P in favor of its own local generic parameter P (T would accomplish the same result)
    public func foo1<P>(_ t: P.Type) -> P { // TOO PERMISSIVE
        return t.init() // Should compile ; does NOT compile
    }
    public static func test_foo1() {
        let c2_1: C2 = D0<C1>().foo1(C2.self) // Should compile ; does compile
        let cX_1: CX = D0<C1>().foo1(CX.self) // Should not compile ; DOES compile
    }



    public func foo2(_ t: P.Type) -> P { // TOO RESTRICTIVE
        return t.init()
    }
    public static func test_foo2() {
        let c2_2: C2 = D0<C1>().foo2(C2.self) // Should compile ; does NOT compile
        let cX_2: CX = D0<C1>().foo2(CX.self) // Should not compile ; does not compile
    }



    // Hardcoded to match the constraint that is *on P*
    public func foo3<T: C0>(_ t: T.Type) -> T { // TOO PERMISSIVE
        return t.init()
    }
    public static func test_foo3() {
        let c0_3: C0 = D0<C1>().foo3(C0.self) // Should not compile ; DOES compile
    }



    // Hardcoded to match the actual generic parameter of my example
    public func foo4<T: C1>(_ t: T.Type) -> T { // HARDCODED TO MATCH MY SINGLE EXAMPLE
        return t.init()
    }
    public static func test_foo4() {
        let c2_4: C2 = D0<C1>().foo4(C2.self) // Should compile ; does compile
        let c0_4: C0 = D0<C1>().foo4(C0.self) // Should not compile ; does not compile
        let cX_4: CX = D0<C1>().foo4(CX.self) // Should not compile ; does not compile
    }
}

Первый пример, foo0, это то, что я ожидал бы работать, но это не компилируется В пятом примере, foo4, я жестко закодировал обобщенный параметр c P как C1, как он должен разрешаться в D0<C1>, что я использую в каждом тесте. Это работает, как и ожидалось, но больше не является обобщенным c.

Я утверждаю, что foo0 должен компилироваться, и (при D0<C1>) имеет то же поведение во время компиляции, что и foo4.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...