Swift: общие протоколы

У меня есть несколько быстрых структур, для которых соответствие протоколу создается с помощью отдельных расширений с одинаковыми именами методов, которые отличаются только типами возврата, которые зависят от структуры. Вдобавок к этому я хочу использовать их в общей функции, которая вызывает функцию, соответствующую протоколу для универсального типа). Я пытался сделать это так: //: Детская площадка - существительное: место, где люди могут играть

import UIKit

protocol FooProt {
typealias T;
static func createMe<T>()->T;
}


struct FooStruct{

}


extension FooStruct: FooProt{
typealias T = FooStruct;
static func createMe  () -> FooStruct{
    return  FooStruct();
}

}


class Creator{
fun  createOne<T where T:FooProt>(type:T.Type){
   let instance  =  T.createMe();
} 

}

К сожалению, я получаю следующую ошибку: /var/folders/sn/78_zvfd15d74dzn01mdv258h0000gq/T/./lldb/3741/playground6.swift:7: 17: note: протокол требует функцию createMe () с типом '() -> T '(aka' ‹τ

import UIKit

protocol FooProt {
typealias T;
static func createMe<T>()->T;
}


struct FooStruct{

}


extension FooStruct: FooProt{
typealias T = FooStruct;
static func createMe  () -> FooStruct{
    return  FooStruct();
}

}


class Creator{
fun  createOne<T where T:FooProt>(type:T.Type){
   let instance  =  T.createMe();
} 

}
0> () -> τ
import UIKit

protocol FooProt {
typealias T;
static func createMe<T>()->T;
}


struct FooStruct{

}


extension FooStruct: FooProt{
typealias T = FooStruct;
static func createMe  () -> FooStruct{
    return  FooStruct();
}

}


class Creator{
fun  createOne<T where T:FooProt>(type:T.Type){
   let instance  =  T.createMe();
} 

}
0 ') статическая функция createMe () -> T;

Что именно здесь не соответствует и есть ли обходной путь?


person hakkurishian    schedule 19.11.2015    source источник


Ответы (2)


Есть несколько проблем с вашим кодом. С одной стороны, вы определили протокол со связанным типом. Однако вы определяете свой метод createMe () как универсальный, который использует какой-то другой тип. Я не думаю, что это было твоим намерением. Я думаю, вы намеревались создать метод createMe (), который возвращает тот же тип, что и тип, связанный с протоколом. В этом случае вам нужно удалить из метода createMe (). Кроме того, имя createMe () подразумевает, что вы не просто возвращаете какой-либо тип, а тип объекта, для которого вызывается этот метод. В этом случае вам даже не нужен протокол связанного типа. Вам просто нужен протокол с ограничением Self, который позволяет сделать ваш код немного проще. В методе createOne вашего создателя ограничение типа более сложное, чем необходимо.

Я думаю, вам нужен следующий код:

protocol FooProt {
    static func createMe()->Self;
}


struct FooStruct{
}


extension FooStruct: FooProt {
    static func createMe() -> FooStruct {
        return FooStruct();
    }
}


class Creator{
    func createOne<T:FooProt>(type: T.Type) -> T {
        return T.createMe()
    }
}


let foo = Creator().createOne(FooStruct.self)
person Tom Pelaia    schedule 19.11.2015
comment
Кроме того, я думаю, что для этого конкретного случая использования даже лучше определить ваш протокол, чтобы иметь инициализатор вместо статического метода. Это снизит нагрузку на ваш код и сделает его более общим и нормализованным. - person Tom Pelaia; 19.11.2015
comment
Спасибо ! Моя ошибка заключалась в игнорировании способности использовать себя в протоколе. Это решает все мои проблемы! Я сделал id точно так же, как указано выше, и, похоже, он работает! - person hakkurishian; 19.11.2015

Вот альтернативное решение с использованием инициализатора в протоколе вместо статического метода.

protocol FooProt {
    init()
}


struct FooStruct{
}


extension FooStruct: FooProt {
}


class Creator{
    func createOne<T:FooProt>(type: T.Type) -> T {
        return T.init()
    }
}


let foo = Creator().createOne(FooStruct.self)
person Tom Pelaia    schedule 19.11.2015