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

在Swift子类中添加便捷初始化器

令狐和裕
2023-03-14
问题内容

作为学习练习,我尝试实现一个子类,SKShapeNode该子类提供一个新的便捷初始化器,该初始化器采用一个数字并构造一个ShapeNode,该ShapeNode是一个数字宽度和高度的平方。

根据《雨燕书》:

规则1

如果您的子类没有定义任何指定的初始化器,它将自动继承其所有超类的指定初始化器。

规则二

如果您的子类提供了其所有超类指定初始化器的实现(通过按照规则1继承它们,或通过提供自定义实现作为其定义的一部分),那么它将自动继承所有超类便利性初始化器。”

但是,以下类不起作用:

class MyShapeNode : SKShapeNode {
    convenience init(squareOfSize value: CGFloat) {
        self.init(rectOfSize: CGSizeMake(value, value))
    }
}

相反,我得到:

Playground execution failed: error: <REPL>:34:9: error: use of 'self' in delegating initializer before self.init is called
        self.init(rectOfSize: CGSizeMake(value, value))
    ^
<REPL>:34:14: error: use of 'self' in delegating initializer before self.init is called
    self.init(rectOfSize: CGSizeMake(value, value))
         ^
<REPL>:35:5: error: self.init isn't called on all paths in delegating initializer
}

我的理解是,MyShapeNode应该继承所有SKShapeNode的便捷初始化器,因为我没有实现自己指定的任何初始化器,并且由于便捷初始化器正在调用init(rectOfSize),另一个便捷初始化器应该可以工作。我究竟做错了什么?


问题答案:

我对Initializer
Inheritance的理解与您的理解相同,并且我认为我们都与本书所陈述的保持一致。我认为这不是解释性问题,也不是对规定规则的误解。也就是说,我认为您没有做错任何事情。

我在Playground中测试了以下内容,它可以按预期工作:

class RectShape: NSObject {
    var size = CGSize(width: 0, height: 0)
    convenience init(rectOfSize size: CGSize) {
        self.init()
        self.size = size
    }
}

class SquareShape: RectShape {
    convenience init(squareOfSize size: CGFloat) {
        self.init(rectOfSize: CGSize(width: size, height: size))
    }
}

RectShape继承自NSObject且未定义任何指定的初始值设定项。因此,根据规则1,它继承了所有NSObject指定的初始化程序。在为实例进行设置之前,我在实现中提供的便捷初始化程序正确地委派给了指定的初始化程序。

SquareShape从继承RectShape,不提供指定的初始值设定项,按照规则1的规定,继承所有SquareShape的指定的初始值设定项。根据规则2,它还继承了中定义的便捷初始化程序RectShape。最后,定义的便捷初始化程序SquareShape正确地委派给继承的便捷初始化程序,后者又委托给继承的指定初始化程序。

因此,鉴于您没有做错任何事且我的示例按预期运行,我在推断以下假设:

因为SKShapeNode是用Objective-
C编写的,所以该语言没有强制执行“每个便利初始化程序必须从同一类调用另一个初始化程序”的规则。因此,也许便利初始化SKShapeNode器实际上并未调用指定的初始化器。因此,即使子类MyShapeNode按预期继承了便利初始化程序,它们也无法正确地委派给继承的指定初始化程序。

但是,这只是一个假设。我可以确认的是,在我自己创建的两个类上,该机制都按预期工作。



 类似资料:
  • 问题内容: 我正在寻找类似于Objective-C的class方法的行为,因为该方法在类初始化时被调用一次,此后不再被调用。 一个简单的闭合将非常时尚!而且很显然,当我们在结构闭包中使用“ s”而不是“ s”时,这一切都将非常匹配! 问题答案: 如果您有一个Objective-C类,最简单的方法就是重写。但是,请确保您的类的 子 类也被覆盖,否则您的类的 子 类可能会被多次调用!如果需要,可以使用

  • 问题内容: 我正在尝试创建UIBezierPath的子类,以添加一些对我有用的属性。 编辑:我需要这个,因为在我的代码中我写 并导致编译错误: “必须调用超类’UIBezierPath’的指定初始化程序” 我试图在子类中添加该初始化器,但似乎不起作用。 你能帮我吗? 问题答案: 注意 :此问题已在iOS 9中得以解决,在该版本中,API已被重写为存在,其他所有(方便初始化程序)也是如此。 问题 简

  • 我找不到任何关于这个具体案例的具体SO帖子,所以我想问一下我认为是/否的问题。 以下是JLS§12.4.2(Java SE 8),清单6-7: 我的问题是:这是否意味着子类的final static变量在超类的静态初始化之前初始化(假设final static作为其声明的一部分初始化)?

  • 问题内容: 我正在跟踪Swift和Objective-C Runtime,它适用于常规方法。 我喜欢使用init方法,据我了解,init就像一个类方法。因此,我尝试将初始化作为实例和类方法。但这似乎不起作用 我可以使用Objective C使其工作,只是想知道如何在Swift中使其工作 摘录自我的要旨 问题答案: 为方法创建选择器时,应使用Obj C方法签名作为选择器的基础,因为使用Obj C运行

  • 问题内容: 我刚刚创建了一个类,并给了它一些变量。不幸的是,我无法在中访问这些变量。但是,相同的语法也可以在游乐场中使用… 问题答案: 类声明 的语法为: 您的include 声明本身不是 声明 ,而是 声明 -特别是带有infix运算符的 二进制表达式 。

  • 问题内容: 我有一个初始化为的变量: 问题是,在某个时候,我需要重置此变量,以便在更改后可以再次初始化。但是如果我将类设置为可选的话,LLVM在尝试将它设置为时会给我一个错误。如果我只是使用将其重置在代码中的某个位置,它将最终显示为。 有没有一种方法可以使用并允许自己重置? 问题答案: 懒惰是明确的仅一次初始化。您要采用的模型可能只是按需初始化模型: 现在,只要是,它会被初始化并返回。可以通过设置