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

即使协议要求给定类型,也必须强制转换

相化
2023-03-14
问题内容

我有以下代码:

import UIKit

protocol Fooable: class where Self: UIViewController {
    func foo()
}

class SampleViewController: UIViewController, Fooable {

    func foo() {
        print("foo")
    }
}

let vc1: Fooable = SampleViewController()
let vc2: Fooable = SampleViewController()


// vc1.show(vc2, sender: nil) - error: Value of type 'Fooable' has no member 'show'

// (vc1 as! UIViewController).show(vc2, sender: nil) - error: Cannot convert value of type 'Fooable' to expected argument type 'UIViewController'

(vc1 as! UIViewController).show((vc2 as! UIViewController), sender: nil)

注释行无法编译。

为什么UIViewController即使Fooable协议要求,我也必须强制将协议类型对象强制转换为符合该对象类型的对象UIViewController


问题答案:

采用该协议Fooable告诉编译器此特定UIViewController响应foo(),至少不会更多。

在相反的结论,Fooable没有 成为UIViewController必然。

如果受影响的类不是,约束Self: UIViewController只是编译器 在编译时 抱怨的另一信息。UIViewController

在您的情况下SampleViewControllerFooable对编译器进行批注仅知道SampleViewController对作出响应foo()。它不知道类型实际上是的子类UIViewController

因此,如果要访问具体类的属性,请不要在协议中为具体类注释。

但是,您可以将show方法和其他常见属性/方法添加到协议中

protocol Fooable: class where Self: UIViewController {
    func foo()
    func show(_ vc: Fooable, sender: Any?)
}

那么您可以使用,Fooable因为编译器知道采用协议的类型会响应该方法。

例如,当您要创建异构但受限制的集合类型时,将类型注释为协议的合适做法是

let array : [CustomStringConvertible] = ["Foo", 1, false]
array.forEach{ print("\($0)")}

该代码使用description所有项目都响应的属性打印这三个项目。编译器可识别的三个项目如
其中有一个类型的description财产,还不如StringIntBool

更新:

在Swift 5中,实现了对超类约束协议的支​​持。



 类似资料:
  • 问题内容: 在Objective-C中,您可以将类型定义为给定类并实现协议: 这将表明返回的值是实现给定协议的值。有没有办法在Swift中执行类似的操作? 问题答案: 您可以这样做: 这定义了一个函数,该函数返回类型为“SomeType”和协议“SomeProtocol”的对象,并返回符合这些条件的对象。

  • 强制类型转换 隐式类型转换:隐式类型转换又称为自动类型转换,隐式类型转换可分为三种:算术转换、赋值转换和输出转换。 显式类型转换:显式类型转换又称为强制类型转换,指的是使用强制类型转换运算符,将一个变量或表达式转化成所需的类型,这种类型转换可能会造成数据的精度丢失。 数据有不同的类型,不同类型数据之间进行混合运算时必然涉及到类型的转换问题。 转换的方法有两种: 自动转换(隐式转换):遵循一定的规则

  • 如何定制协议 实际上制定自己的协议是比较简单的事情。简单的协议一般包含两部分: 区分数据边界的标识 数据格式定义 一个例子 协议定义 这里假设区分数据边界的标识为换行符”\n”(注意请求数据本身内部不能包含换行符),数据格式为Json,例如下面是一个符合这个规则的请求包。 {"type":"message","content":"hello"}   注意上面的请求数据末尾有一个换行字符(在PHP中

  • 问题内容: 我想创建一个具有某种类型并且也符合协议的属性,就像我在Objective-C中所做的那样: 我要寻找的是指定可以使用也符合CustomProtocol的UIViewController类型的对象设置属性,以便清楚什么是基类。我知道我可以只使用短类存根来获得相同的结果,即 但这似乎不是最干净的方法。 问题答案: 我想不出一种在Swift中表达这一点的好方法。类型的语法是: 类型→数组类型

  • 问题内容: “让f = e为[测试],让g = e为![测试]”总是会出错。我有一个必须发送[Test]到的功能。将A转换为Test易于使用。但是当涉及到数组时,我必须遍历所有数据。有什么好的方法可以将[A]转换为[Test]。 问题答案: 不同代码的答案是正确的,但它也是重要的是要明白,为什么你不能只是重新解释数据,而不 东西 做一个O(n)的转换行走,虽然在一个盒子包装的每个元素。 是一个数组

  • 问题内容: 我需要为JTree使用自定义单元格渲染器,以便在每个单元格上添加一些JLabel。然后允许用户单击这些标签,而无需先选择单元格。 因此,我创建了一个Renderer,它返回一个包含DefaultTreeCellRenderer和2 JLabel的JPanel。 然后,我创建了编辑器,以允许用户通过MouseListener来单击这些标签。一切工作正常,除了用户必须在单击标签之前选择单元