Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift:使用相同的“制造两种类型”;形状“;遵守共同协议_Swift_Swift Protocols - Fatal编程技术网

Swift:使用相同的“制造两种类型”;形状“;遵守共同协议

Swift:使用相同的“制造两种类型”;形状“;遵守共同协议,swift,swift-protocols,Swift,Swift Protocols,我有两种不同的类型,它们表示相同的数据,并且具有完全相同的“形状”。这两种不同的类型是代码gen'd,我不得不处理它们。但是,我想让它们符合一个通用协议,这样我就可以对这两种类型进行相同的处理。下面是一个例子: 假设这是我的两种代码gen'd类型,我一直在使用: struct User1 { var email: String var name: Name struct Name { var givenName: String v

我有两种不同的类型,它们表示相同的数据,并且具有完全相同的“形状”。这两种不同的类型是代码gen'd,我不得不处理它们。但是,我想让它们符合一个通用协议,这样我就可以对这两种类型进行相同的处理。下面是一个例子:

假设这是我的两种代码gen'd类型,我一直在使用:

struct User1 {
    var email: String
    var name: Name
    
    struct Name {
        var givenName: String
        var familyName: String
    }
}

struct User2 {
    var email: String
    var name: Name
    
    struct Name {
        var givenName: String
        var familyName: String
    }
}
我希望能够互换使用这些类型,因此我创建了两个协议,它们可以遵循:

protocol NameRepresenting {
    var givenName: String { get }
    var familyName: String { get }
}

protocol UserRepresenting {
    var email: String { get }
    var name: NameRepresenting { get }
}
然后我试图使他们符合:

extension User1.Name: NameRepresenting {}
// Error: Type 'User1' does not conform to protocol 'UserRepresenting'
extension User1: UserRepresenting {}

extension User2.Name: NameRepresenting {}
// Error: Type 'User2' does not conform to protocol 'UserRepresenting'
extension User2: UserRepresenting {}

我希望上面的方法能起作用,但是编译失败,上面评论了错误。有没有什么好办法使这两种类型符合通用协议,以便我可以互换使用它们?

生成的结构的
name
属性具有type
name
,而不是协议要求的
name。Swift目前还不支持协变回报:(

您可以做的是添加关联的类型需求:

protocol UserRepresenting {
    associatedtype Name : NameRepresenting
    var email: String { get }
    var name: Name { get }
}
这要求符合项的类型必须符合
namefresentation
,并且是
name
属性的类型

但是,现在它有一个关联的类型要求,您不能使用
userrepresentation
作为变量/函数参数的类型。您只能在泛型约束中使用它。因此,如果您有一个函数采用
userrepresentation
,您需要这样编写:

func someFunction<UserType: UserRepresenting>(user: UserType) {

}
这可能适用于您的情况,也可能不适用于您的情况。如果不适用,您可以编写一个类型橡皮擦:

struct AnyUserRepresenting : UserRepresenting {
    var email: String
    var name: Name
    struct Name : NameRepresenting {
        var givenName: String
        var familyName: String
    }

    init<UserType: UserRepresenting>(_ userRepresenting: UserType) {
        self.name = Name(
            givenName: userRepresenting.name.givenName,
            familyName: userRepresenting.name.familyName)
        self.email = userRepresenting.email
    }
}
struct AnyUserRepresenting:UserRepresenting{
var电子邮件:String
变量名称:名称
结构名称:namefresenting{
var givenName:字符串
var familyName:字符串
}
init(uUserRepresentating:UserType){
self.name=名称(
givenName:userrepresentating.name.givenName,
familyName:UserRepresentating.name.familyName)
self.email=userrepresentation.email
}
}
现在,您可以将任何表示
用户转换为该
表示
的任何用户,并改为使用表示
任何用户

struct AnyUserRepresenting : UserRepresenting {
    var email: String
    var name: Name
    struct Name : NameRepresenting {
        var givenName: String
        var familyName: String
    }

    init<UserType: UserRepresenting>(_ userRepresenting: UserType) {
        self.name = Name(
            givenName: userRepresenting.name.givenName,
            familyName: userRepresenting.name.familyName)
        self.email = userRepresenting.email
    }
}