看完视频here后,我对使用final关键字感到困惑。
以下是视频中的示例图片
这里有两个类Pet作为父类,而Dog作为子类,并且我们有makeNoise(p)的函数实现,该函数以Pet实例为参数。但是在后台,编译器在此方法中再插入几行用于检查类。
由于makeNoise(p)将参数作为Pet实例,因此编译器应直接从Pet类中调用属性“名称”,因为方法参数适用于此类。
为什么编译器会担心子类中的重写属性,因为该参数是Pet实例并且编译器知道它。是不是
我的问题可能看起来很愚蠢,但是如果有人可以更清楚地解释它,我将不胜感激。
最佳答案
makeNoise(p: Pet)
的参数必须是Pet
,但它不是Pet
本身的直接实例。由于Dog
是Pet
的子类,因此它也是Pet
。因此,在Swift中,有人将Dog
实例传递给makeNoise
是完全有效的,在这种情况下,将调用noise
的重写版本。同样,此狗可能已为name
选择了不同的值。
动态类型
这称为p
的“动态类型”。 p
的编译时类型为Pet
,但是编译器必须考虑以下事实:p
的运行时类型可能是覆盖某些内容的Pet
子类。这称为p
的“动态类型”。在WWDC 2015时使用的Swift 1和Swift 2中,在对象上使用.dynamicType
语法确定其运行时类型。 Swift 3使用type(of: object)
全局函数。这不是您经常需要的,但是它演示了编译器如何允许子类充当其父类并仍然覆盖它们。final
final
告诉编译器该类将不会被子类化,或者该属性或方法将不会被覆盖。这样,它就不需要检查替代。
Swift 3的变化
如果我没记错的话,今年的WWDC 2016 Swift性能 session 没有一次提到final
关键字。尽管它在Swift 3中仍然可用并且具有相同的目的,但是有新的方法可以防止子类化和覆盖。这是通过访问控制。 Swift 3引入了open
关键字,与public
不同。
public
–模块open
–类或方法不仅可以被任何人访问,还可以被子类化(对于类而言)或被重写(对于方法而言)。 我不确定是否像
final
一样向Swift编译器传达它不需要进行额外的类型检查。关于ios - 快速优化性能说明,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39550709/