当前位置: 首页 > 面试题库 >

只能通过使用最终类才能满足的Swift协议要求

谷梁镜
2023-03-14
问题内容

我在Swift上建模所有者/所有者方案:

class Owner<T: Ownee> {
     // ...
}

protocol Ownee {
    var owner: Owner<Self> { get }
}

然后我有一对遵循上述建模类型的教授/学生:

class Professor: Owner<Student> {
    // ...
}

class Student: Ownee {
    let professor: Professor
    var owner: Owner<Student> {  // error here (see below)
        return professor
    }

    init(professor: Professor) {
        self.professor = professor
    }
}

但是我var ownerStudent类中的定义上收到以下错误:

非最终课程(“学生”)无法满足协议“ Ownee”的要求“所有者”,因为它在非参数,非结果类型的位置使用了“自我”

我试图了解导致此错误的原因,为什么将类定为Studentfinal可以解决该问题,以及是否存在一些解决方法能够以不同的方式对此模型进行建模而不将其定为final。我已经搜索过该错误,但到目前为止还没有发现太多。


问题答案:

错误是正确的。您必须将类定型,因为没有子类可以符合您的协议Ownee

考虑以下子类:

class FirstGradeStudent: Student {
   // inherited from parent
   // var owner: Owner<Student> {
   //     return professor
   //  }
}

如您所见,var owner: Owner<Student>由于其父级,它必须实现,但是应该var owner: Owner<FirstGradeStudent>改为实现,因为协议包含var owner: Owner<Self> { get },在这种情况下SelfFirstGradeStudent

解决方法

1: 定义的超类Ownee,它应由Owner

class Owner<T: OwneeSuper> {
    // ...
}

protocol OwneeSuper {}    
protocol Ownee: OwneeSuper {
    associatedtype T: OwneeSuper
    var owner: Owner<T> { get }
}

OwneeSuper只是解决此问题的一种解决方法,否则我们将使用:

protocol Ownee {
    associatedtype T: Ownee
    var owner: Owner<T> { get }
}

2. 在符合的类中Ownee,您必须associatedtype通过定义以下内容将的抽象类型转换为具体类typealias

class Student: Ownee {
    typealias T = Student // <<-- define the property to be Owner<Student>
    let professor: Professor
    var owner: Owner<T> { 
        return professor
    }

    init(professor: Professor) {
        self.professor = professor
    }
}

3. 子类现在可以使用属性,该属性将是您定义的类型:

class FirstGradeStudent: Student {
    func checkOwnerType() {
        if self.owner is Owner<Student> { //warning: 'is' test is always true
            print("yeah!")
        }
    }
}


 类似资料:
  • 问题内容: 为什么我可以做到这一点而没有任何错误: 虽然我定义了这个: 如果我的协议中的定义大部分被忽略(getter,setter定义),为什么我仍要使用它们? 问题答案: 根据官方文件: 可以通过多种方式通过符合类型来满足吸气剂和设置剂的要求。如果属性声明同时包含get和set关键字,则符合条件的类型可以使用存储的变量属性或既可读又可写的计算属性(即,同时实现getter和setter的)来实

  • 问题内容: 我有一个协议P1,它提供了Objective-C可选功能之一的默认实现。 当我提供可选功能的默认实现时,会出现警告 编译器警告: 版: 斯威夫特:3 Xcode:8(公开发行) 尝试: 尝试添加但无济于事 题: 我该如何解决? 有没有解决的办法? 码: 问题答案: 虽然我认为我可以回答您的问题,但这不是您想要的答案。 TL; DR: 功能可能当前不在协议扩展中。您可以创建一个基类,尽管

  • 问题内容: 为什么以下代码会产生错误? 这个类似问题的答案很有意义。但是,在我的示例中,该属性为get-only。为什么不行呢?是Swift的缺点,还是有一定的道理呢? 问题答案: 没有真正的理由为什么不可能做到这一点,只读属性要求 可以 是协变的,因为从完全合法的类型化的属性返回实例。 Swift暂时不支持。为此,编译器将必须在协议见证表和符合的实现之间生成一个thunk,以执行必要的类型转换。

  • 问题内容: 以下代码使快速(3,3.1,4)编译器崩溃: 我可能天真地希望编译器将其推断为具有签名的Function Type ,之后,我可以这样称呼它: 我想我的问题是:显然,编译器应该执行除崩溃以外的其他操作,但是Swift目前应该支持这种语法吗? 问题答案: 如您所说,编译器永远不会崩溃;这确实是一个错误,已在此处提交。Swift团队成员Slava Pestov在其中说: 我们计划使MyPr

  • 【注意】关于 Navicat Cloud 服务的许可协议,请点击这里。 【重要说明】本协议 (即 “EULA”) 是已获本软件许可的个人、公司或组织 (“您” 或 “客户”) 与卓软数码科技有限公司之间订立的法律协议。安装和使用本软件的行为表示“客户”接受了本软件, 并且同意本协议的条款。请在完成安装过程和使用本软件之前仔细阅读本协议。安装和 / 或使用本软件的行为表示您确认接受了本软件, 并且同

  • IMPORTANT: THIS SOFTWARE END USER LICENSE AGREEMENT ("EULA") IS A LEGAL AGREEMENT BETWEEN YOU (EITHER AN INDIVIDUAL OR, IF PURCHASED OR OTHERWISE ACQUIRED BY OR FOR AN ENTITY, AN ENTITY) AND PREMIUMSO