Swift构造器继承链

 类类型的构造器代理

Swift构造器需遵循以下三大规则:

  1. 指定构造器必须调用它直接父类的指定构造器方法
  2. 便利构造器必须调用同一个类中定义的其他初始化方法
  3. 便利构造器在最后必须调用一个指定构造器

两段式构造过程

Swift 中类的构造过程包含两个阶段。第一个阶段,类中的每个存储型属性赋一个初始值。当每个存储型属性的初始值被赋值后,第二阶段开始,它给每个类一次机会,在新实例准备使用之前进一步自定义它们的存储型属性。

两段式构造过程的使用让构造过程更安全,同时在整个类层级结构中给予了每个类完全的灵活性。两段式构造过程可以防止属性值在初始化之前被访问,也可以防止属性被另外一个构造器意外地赋予不同的值。

Swift提供了4种安全检查是开发者必须遵循的。

  1. 若子类中定义了父类没有的变量,则在子类的指定构造器中需先对该变量赋值,再调用父类的构造器。
  2. 若要在子类的指定构造器中修改继承来的变量的值,则需先调用父类的构造器。
  3. 若要在子类的便利构造器中修改任意变量的值,则需先调用同类的构造器。
  4. 所有属性被赋初始值后(即第一阶段结束后)才能调用实例方法。

阶段 1

类的某个指定构造器或便利构造器被调用。

完成类的新实例内存的分配,但此时内存还没有被初始化。

指定构造器确保其所在类引入的所有存储型属性都已赋初值。存储型属性所属的内存完成初始化。

指定构造器切换到父类的构造器,对其存储属性完成相同的任务。

这个过程沿着类的继承链一直往上执行,直到到达继承链的最顶部。

当到达了继承链最顶部,而且继承链的最后一个类已确保所有的存储型属性都已经赋值,这个实例的内存被认为已经完全初始化。此时阶段 1 完成。

阶段 2

从继承链顶部往下,继承链中每个类的指定构造器都有机会进一步自定义实例。构造器此时可以访问 self、修改它的属性并调用实例方法等等。

最终,继承链中任意的便利构造器有机会自定义实例和使用 self

构造器的继承和重写

规则:

  • 若定义的子类构造器与父类指定构造器相匹配,则需要在定义子类构造器时加上override 修饰符。
  • 若定义的子类构造器与父类便利构造器相匹配,不需要加override修饰符。
  • 若父类的指定构造器无参数,且在子类构造器中没有自定义父类的属性,那么在子类指定构造器中可以省略 super.init()
import UIKit

class lei{
    var name: String?
    init(){
        self.name = "123"
    }
}

class sublei: lei{
    var color: String
    init(color: String) {
        self.color = color
        //隐式调用super.init()
    }
}

构造器的自动继承

假设你为子类中引入的所有新属性都提供了默认值,以下 2 个规则将适用: 

规则 1: 如果子类没有定义任何指定构造器,它将自动继承父类所有的指定构造器。

import UIKit

class lei{
    var name: String?
    init(_ name: String){
        self.name = name
    }
}

class sublei: lei{
    var color = "123"
}

let a = sublei("abc")

规则 2: 如果子类提供了所有父类指定构造器的实现——无论是通过规则 1 继承过来的,还是提供了自定义实现——它将自动继承父类所有的便利构造器。 即使你在子类中添加了更多的便利构造器,这两条规则仍然适用。

注意: 子类可以将父类的指定构造器实现为便利构造器来满足规则 2。 

import UIKit

class lei{
    var name: String?
    init(_ name: String){
        self.name = name
    }
    convenience init(){
        self.init("abc")
    }
}

class sublei: lei{
    var color: String?
    init(_ name: String, _ color: String?){
        self.color = color
        super.init(name)
    }
    convenience override init(_ name: String) {
        self.init(name, nil)
    }
}


let one = sublei()

可失败构造器的重写与继承

语法:init?()

可失败构造器会创建一个类型为自身类型的可选类型的对象。你通过 return nil语句来表明可失败构造器在何种情况下应该 “失败”。

严格来说,构造器都不支持返回值。因为构造器本身的作用,只是为了确保对象能被正确构造。因此你只是用 return nil表明可失败构造器构造失败,而不要用关键字 return来表明构造成功。

重写可失败构造器可以在子类中定义一个非可失败构造器。

注意:

可以用非可失败构造器重写可失败构造器,但反过来却不行。

import UIKit

class lei{
    var name: String?
    init(){}
    
    init?(_ name: String){
        if name.isEmpty { return nil }
        self.name = name
    }
}

class sublei: lei{
    override init() {
        super.init()
        self.name = "abc"
    }
    override init(_ name: String) {
        super.init()
        if name.isEmpty{
            self.name = "abc"
        }else{
            self.name = name
        }
    }
}

你可以在子类的不可失败构造器中使用强制解包来调用父类的可失败构造器。比如,下面的 suble子类的 name 属性的值总是 "abc",它在构造过程中使用了父类的可失败构造器 init?(name:):

class sublei: lei {
override init() {
super.init(name: "abc")!
	}
}

 在这个例子中,如果在调用父类的可失败构造器 init?(name:) 时传入的是空字符串,那么强制解包操作会引发运行时错误。不过,因为这里是通过字符串常量来调用它,构造器不会失败,所以并不会发生运行时错误。

必要构造器

在类的构造器前添加 required修饰符表明所有该类的子类都必须实现该构造器:

class SomeClass {
    required init() {
        // 构造器的实现代码
    }
}

在子类重写父类的必要构造器时,必须在子类的构造器前也添加 required修饰符,表明该构造器要求也应用于继承链后面的子类。在重写父类中必要的指定构造器时,不需要添加 override修饰符:

class SomeSubclass: SomeClass {
    required init() {
        // 构造器的实现代码
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/207829.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis主从与哨兵架构详解

目录 主从架构 主从环境搭建 主从复制流程 1. 全量复制 2. 部分复制 主从风暴 哨兵架构 概念 哨兵环境搭建 主从架构 主从环境搭建 1. 复制一份redis.conf文件, 修改下面几行配置 port 6380 pidfile /var/run/redis_6380.pid logfile "6380.log" dir /usr/…

PowerDesigner数据库建模软件的安装

解压: 解压好以后,点击PowerDesigner.exe安装 这个安装的版本是15 选择安装路径,可以默认可以自定义: 直接点next: 全选了 点击next: 点击next: 点finish 汉化: 先把pojie和汉化文件…

Unity中Shader编译目标级别

文章目录 前言一、Shader Model二、Shader编译目标级别法1: #pragma target 3.0法2:#pragma require integers geometry 三、测试代码 前言 针对不同平台的特性,所做的一些功能 一、Shader Model ShaderModel 由微软提出,要求显…

蔚碳科技联合中投会发布国内首个 ESG 尽职调查服务标准

11 月 26 日,蔚碳(上海)科技有限公司(以下简称“蔚碳科技”)受邀出席由深圳市人民政府主办,深圳市发展和改革委员会、深圳市生态环境局、龙岗区人民政府共同承办的 2023 碳达峰碳中和论坛暨深圳国际低碳城论…

使用 SDKMAN 管理多版本本地 Java 环境---Centos8 Windows

文章目录 windows 安装centos8 安装卸载sdkman使用 windows 安装 SDKMAN是一个 jdk 多版本管理工具,类似于 nodejs 中的 nvm。可以在本地存在多个 java 环境,快速切换功能,同时,他不止于 java sdk,还有maven、tomcat等…

WhatsApp群发消息脚本功能介绍及代码分享!

随着社交媒体的普及,通讯应用成为了人们日常沟通的主要工具之一,其中,WhatsApp凭借其简洁、易用的特点,成为了全球广受欢迎的通讯应用之一,除了基础的聊天功能,WhatsApp还提供了一系列辅助工具功能&#xf…

关于 ls -s 输出文件大小的单位问题的讨论

自己看书正好看到这里,正纳闷呢,上网查了下,发现不是我自己在为这个问题感到困惑。 有个大哥提出一个问题: 问题标题: ls -s的单位到底是什么? man ls -s, --size print the alloca…

web前端之css变量的妙用、通过JavaScrip改变css文件中的属性值、querySelector、setProperty

MENU 效果图htmlJavaScripstylequerySelectorsetProperty 效果图 html <div id"idBox" class"p_r w_680 h_160 b_1s_red"><div id"idItem" class"p_a l_0 t_30 w_100 h_100 bc_rgba_255_00_05 radius_50_"></div> …

matlab 基于卡尔曼滤波的GPS-INS的数据融合的导航

1、内容简介 略 25-可以交流、咨询、答疑 2、内容说明 基于卡尔曼滤波的GPS-INS的数据融合的导航 "基于卡尔曼滤波的GPS-INS的数据融合的导航 基于卡尔曼滤波实现GPS-INS组合导航系统" 卡尔曼滤波、GPS、INS、数据融合、导航 3、仿真分析 4、参考论文 略 …

YOLOv8-Seg改进:SENetV2,squeeze和excitation全面升级,效果优于SENet | 2023年11月最新成果

🚀🚀🚀本文改进: SENetV2,squeeze和excitation全面升级,作为注意力机制引入到YOLOv8,放入不同网络位置实现涨点 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1)手把手教你如何训练YOLOv8-s…

FTP协议详解

一&#xff1a;概述 FTP协议是一个用于在计算机网络上在客户端和服务器之间进行文件传输的应用层协议&#xff0c;其英文全称是File Transfer Protocol。是TCP/IP协议簇中的重要一员。客户端和服务器按照FTP的协议规范进行通讯来实现文件传输。 对于FTP服务器好理解&#xff0c…

后仿真 ERROR

后仿真 error ERROR (SFE-23): "input.scs" 252: The instance _57_D32_noxref is referencing an undefined model or subcircuit, parasitic_nwd. Either include the file containing the definition of parasitic_nwd, or define parasitic_nwd before running t…

Adobe ColdFusion文件读取漏洞(CVE-2010-2861)

任务一&#xff1a; 复现漏洞 任务二&#xff1a; 尝试利用漏洞读取目标系统中的“opt/coldfusion8/license.txt"文件 1.环境搭建&#xff08;网上写的密码是admin&#xff0c;就用admin&#xff09; 2.看答案就是一层一层进行路径穿越攻击&#xff0c;这里要注意如果…

Vue+Element-ui实例_在form中动态校验tag标签

1.开发需求 在日常开发中&#xff0c;我们会遇到form表单的动态添加和校验&#xff0c;当我们需要在动态添加的内容中再次动态使用输入框的时候&#xff0c;就会变得很繁琐&#xff0c;我在网上找了很多案例&#xff0c;没有符合自己需求的内容&#xff0c;只好闲暇时间自己搞…

实现优雅的自增枚举类:Python中的枚举与自增技巧

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 枚举类型在编程中扮演着重要的角色&#xff0c;它们为变量赋予了更加清晰的含义。然而&#xff0c;在Python中&#xff0c;实现自增的枚举类并非直接而简单的任务。本文将深入讨论如何通过不同的方式优雅地实现自…

matlab 混沌动力学行为-分岔图-李雅普指数等

1、内容简介 略 24-可以交流、咨询、答疑 2、内容说明 混沌动力学行为-分岔图-李雅普指数等 包含各种类型的混沌模型求解&#xff0c;包含其分叉图、李雅普指数等 混沌、分叉图、李雅普指数 3、仿真分析 略 4、参考论文 略 链接&#xff1a;https://pan.baidu.com/…

JMX的使用

1. 定义和意义 JMX是Java Management Extention的缩写&#xff0c;出发点是让外部通过属性/方法来读取或设置程序状态。对于提供对外服务的程序来说&#xff0c;天生就有这样的能力&#xff0c;Web程序通过HTTP接口对外暴露&#xff0c;RPC应用通过RPC接口暴露。不过带来的问…

matlab simulink 永磁同步电机PI调速控制

1、内容简介 略 27-可以交流、咨询、答疑 2、内容说明 永磁同步电机调速控制 永磁同步电机PI调速控制 永磁同步电机PI调速控制、PMSM 3、仿真分析 略 4、参考论文 略 链接&#xff1a;https://pan.baidu.com/s/1AAJ_SlHseYpa5HAwMJlk1w 提取码&#xff1a;rvol 路…

【Linux】:信号(三)捕捉

信号捕捉 一.sigaction1.基本使用2.sa_mask字段 二.可重入函数三.volatile四.SIGCHLD信号 承接上文 果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号。由于信号处理函数的代码是在用户空间的,处理过程比较复杂,举例如下: 用户程序注册了SIGQUIT信…

React Native环境搭建及Hello World

写这篇博客的目的就是想说,react native 挺简单,但是大部分初级前端会被环境搭建给难住,从而放弃. 环境搭建 环境搭建其实说简单也挺简单的,有经验的前端直接翻看react native中文文档就行,直接按上面来肯定没错 以下以安卓开发,windows配置环境为例,来演示一遍 首先 电脑…