创建: 2018/03/09

完成: 2018/03/10

更新: 2018/04/19 修改小标题  [扩张的定义与使用协议] -> [通过扩张来采用协议]

更新: 2018/09/18 标题里增加英文方面自己快速找到 [Swift4 扩张, 集合] -> [Swift4 扩张(Extenstion), 集合(Set)]

扩张的声明与定义
 扩张的概要

可以对类, 构造体(系统固有的数据类型都算), 枚举型, 协议进行扩张

extension 型名: 协议 { // 协议可省略, 顺序随意
构造函数 // 顺序随意
属性定义 // 除计算型实例属性
方法定义
其他定义 // 嵌套型, 索引等
}

● 可以增加以下新定义

(●) 计算型属性, 计算型和容纳型静态属性(类属性)

      即除容纳型实例属性外的属性

(●) 实例方法, 静态方法(类犯法)

(●) 构造函数

(●) 索引subscript

(●) 嵌套型声明(嵌套型在扩张定义内部用)

● 不可增加计算型实例属性, 属性监听器({willset didset})

 系统固有型的扩张例 

extension String {
//下标数字1
static var zeroUnder: String {
return "\u{2080}"
}
}
 扩张的定义与构造函数 

扩张与构造函数

● 构造体:

  扩张定义的构造函数不会使构造体的默认构造函数和全项目构造函数无效

● 类

扩张只能定义简易构造函数(带convenience), 不能定义指定构造函数

不能定义析构函数

 扩张定义与继承的注意 

● 扩张的东西都自带final

无法被子类重载

不能用扩张去重载父类属性/方法

   
通过扩张来采用协议
 使用扩张来采用协议
class ExtensionSampleClass { // 什么都没有的空类

}
protocol ExtensionSampleProtocol { // 只含一个字符串变量的协议
var sampleString: String { get }
}
extension ExtensionSampleClass: ExtensionSampleProtocol { // 用扩张采用协议
var sampleString: String {
return "ExtensionSampleClass"
}
}

● 同时采用多个时用,隔开

extension SampleDataType: Protocol1, Protocol2, ... { // 多个用,隔开
...
}
 型内已有一部分/全部不定义

型内已有要采用的协议的一部分或全部定义时,

扩张里只需要补充缺少的. 不能改写型定义里已存在的

//内部已有一部分或全部实现
class ExtensionSampleClass2 { // 类里有sampleData
var sampleData: Int = }
protocol ExtensionSampleProtocol2 { // 含sampleString和sampleData的协议
var sampleString: String { get }
var sampleData: Int { get }
}
extension ExtensionSampleClass2: ExtensionSampleProtocol2 { // 只需要实现sampleString即可
var sampleString: String {
return "ExtensionSampleClass"
}
}
   
   
   
协议的扩张
 协议的扩张

● 可以写方法, 计算型属性, 索引subscript

● 不可以写协议里的那种声明, 和容纳型实例/静态变量

●  主要只要协议里东西的实现, 做默认实现

● 改写默认实现不需要override

 标准库的协议已有的扩张 

public protocol Equatable { // 可等协议
static func == (lhs: Self, rhs: Self) -> Bool
} extension Equatable { // 扩张, 这样只需要实现==即可
public static func != (lhs: Self, rhs: Self) -> Bool {
return !(lhs == rhs)
}
}
 协议扩张时对型附加条件

对协议扩张时才能附加条件

● 可附加的条件:

附属型: 协议      表示附属型必须采用指定协议

附属型 == 型    附属型必须是指定的型(可以是typealias后的)

protocol SampleProtocol {  // 样本协议
associatedtype Element // 附属型
...
} extension SampleProtocol where Element: CustomStringConvertable // 附属型Element必须采用CustomStringConvertable {
...
} extension SampleProtocol where Element == String { // 附属型Element必须是String型
...
}
 协议扩张的多重继承 

● 同时采用多个协议时不能有重名属性或方法

● 相当于其他语言的mixin, trait

   
   
集合与协议
 通过哈希值实现高速搜索

● 集合和数组类似, 但不能有重复

● 集合用于不需要重复元素或者需要使用集合运算的情况

● 采用Hashable协议

public protocol Hashable: Equatable { // 继承Equatable, 需要实现==
public var hashValue: Int { get }
}
 集合的声明与初始化 

声明

var s: Set<类型>

初始化, 用数组, 有重复元素自动清除多余的

let setSample: Set<String> = ["a", "a", "b"]
print("setSample.count = \(setSample.count)") //

也可以用init

Set<Int>.init() // []
Set<Int>.init(..<) // Set<T>.init(sequence: Sequence)
 元素的获取

和数组, 哈希表, 字符串一样采用Collection(继承Sequence)

参照: 传送门

 集合运算 

前提: 元素同型

● 采用SetAlgebra(继承Equatable, ExpressibleByArrayLiteral)

● 主要构造函数

 Set<T>.init()  返回空集合
 Set<T>.init(_:S)

用采用Sequence的实例

数组

● 主要属性

 var isBool: Bool { get }  是否为空
   

● 主要方法

S: sequence, 集合, 数组, 范围等

T: Set<T>的T

 func contains(_:T) -> Bool  是否包含指定元素

@discardable

mutating func insert(_:T) -> (inserted: Bool, memberAfterInsert: T)

插入指定元素,

成功返回true和被插入元素

失败返回false和已有元素

@discardable

mutating func remove(_:T) -> T?

删除指定元素

有的话删除并返回被删除元素

没有的话返回nil

 查询集合间关系
 是否包含
 是否包含  A.isSuperset(of: B)
 是否真包含  A.isStrictSuperset(of: B)
 是否是子集
 是否是子集  A.isSubset(of: B)
 是否是真子集  A.isStrictSubset(of: B)
 不相交  A.isDisjoint(with: B)
 集合间运算

和集合(并集)

A+B

A.union(B) -> Set

A.formUnion(B)

差集合

A-B

A.substracting(B) -> Set

A.substract(B)

积集合(交集)

A*B ()

A.intersection(B) -> Set

A.formIntersection(B)

对称差集合

(A+B)-(A*B)

A.symmetricDifference(B) -> Set

A.formSymmetricDifference(B)

   
   
 OptionSet协议 

OptionSet协议

protocol OptionSet: SetAlgebra, RawRepresentation {
// SetAlgebra(继承Equatable, ExpressibleByArrayLiteral)
// RawRepresentable协议带有rawValue, init?(rawValue:)
associatedtype Element = Self
init(rawValue: Self.RawValue)
}

RawRepresentable协议

protocol RawRepresentable {
associatedtype RawValue
init?(rawValue: Self.RawValue)
public var rawValue: Self.RawValue { get }
}

OptionSet的扩张(一部分)

extension OptionSet {
public func union(_ other: Self) -> Self {
var r: Self = Self(rawValue: self.rawValue) // 生成self的copy
r.formUnion(other) // 生成和集合, 并集, 存在于SetAlgebra协议
return r
}
public func intersection(_ other: Self) -> Self {
... // 省略, 和union一样
}
} extension OptionSet where Element == Self { // OptionSet内部associatedtype Element = Self, 所以这里默认成立
public func contains(_ member: Self) -> Bool {
return self.isSuperset(of: member)
}
@discardable
public mutating func remove(_ member: Element) -> Element? {
let r = isSuperset(of: member) ? Optional(Member) : nil
self.subtract(member) // 存在于SetAlgebra协议
return r
}
} extension OptionSet where RawValue: FixedWidthInteger { // Int, UInt等采用FixedWidthInteger, 可以进行位运算
public init() {
self.init(rawValue: )
}
public mutating func formUnion(_ other: Self) {
self = Self(rawValue: self.rawValue | other.rawValue)
}
public mutating func formIntersection(_ other: Self) {
self = Self(rawValue: self.rawValue & other.rawValue)
}
}

● 要想使用默认实现, 只需定义RawValue型为Int, UInt

         并放一个rawValue属性

● 不带任何选项的实例推荐用[]来生成

● 用法: 放置选项, 相当于C, ObjC的比特列放置选项

可以去查看是否包含某选项, 是否包含某些选项等

struct SampleOptionSet: OptionSet { // 例, 四个选项optionA, B, C, D
typealias RawValue = UInt
let rawValue: UInt
static let optionA: SampleOptionSet = SampleOptionSet.init(rawValue: << )
static let optionB: SampleOptionSet = SampleOptionSet.init(rawValue: << )
static let optionC: SampleOptionSet = SampleOptionSet.init(rawValue: << )
static let optionD: SampleOptionSet = SampleOptionSet.init(rawValue: << )
}
   
   
   

Swift4 扩张(Extenstion), 集合(Set)的更多相关文章

  1. Redis底层探秘(四):整数集合及压缩列表

    整数集合 整数集合(intset)是集合键的底层实现之一,当一个集合只包含 整数值元素,并且这个集合的元素数量不多时,Redis就会使用郑书记和作为集合键的底层实现. 整数集合的实现 整数集合是red ...

  2. Java集合---ArrayList的实现原理

    目录: 一. ArrayList概述 二. ArrayList的实现 1) 私有属性 2) 构造方法 3) 元素存储 4) 元素读取 5) 元素删除                 6) 调整数组容量 ...

  3. ArrayList集合的实现原理

    一. ArrayList概述: ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存. ArrayList不是线程安全的,只能用在单线程环境 ...

  4. 重新开始学习javase_集合_List

    一,List之ArrayList(转:http://blog.csdn.net/zheng0518/article/details/42198205) 1. ArrayList概述: ArrayLis ...

  5. Java集合ArrayList源码解读

    最近在回顾数据结构,想到JDK这样好的代码资源不利用有点可惜,这是第一篇,花了心思.篇幅有点长,希望想看的朋友认真看下去,提出宝贵的意见.  :) 内部原理 ArrayList 的3个字段 priva ...

  6. ava集合---ArrayList的实现原理

    一.ArrayList概述 ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存 ArrayList不是线程安全的,只能用在单线程环境下,多 ...

  7. Java多线程 阻塞队列和并发集合

    转载:大关的博客 Java多线程 阻塞队列和并发集合 本章主要探讨在多线程程序中与集合相关的内容.在多线程程序中,如果使用普通集合往往会造成数据错误,甚至造成程序崩溃.Java为多线程专门提供了特有的 ...

  8. Java集合:ArrayList的实现原理

    Java集合---ArrayList的实现原理   目录: 一. ArrayList概述 二. ArrayList的实现 1) 私有属性 2) 构造方法 3) 元素存储 4) 元素读取 5) 元素删除 ...

  9. JDK源码学习之 集合实现类

    一.HashMap (1) 简介:java1.8版本之前HashMap的结构图如下: 数组的每个元素都是一个单链表的头节点,链表是用来解决冲突的,如果不同的key映射到了数组的同一位置处,就将其放入单 ...

随机推荐

  1. linux mail 发邮件

    system('echo "'.$xmlHeader.$xmlBody.$xmlFooter.'" | mail -s "百度新闻源生成成功,地址=>http:// ...

  2. python学习之-- 事件驱动模型

    目前主流的网络驱动模型:事件驱动模型 事件驱动模型:也属于生产者/消费者结构,通过一个队列,保存生产者触发的事件,队列另一头是一个循环从队列里不断的提取事件.大致流程如下:1:首先生成一个事件消息队列 ...

  3. 钱币兑换问题---hdu1284(完全背包)

    Problem Description 在一个国家仅有1分,2分,3分硬币,将钱N兑换成硬币有很多种兑法.请你编程序计算出共有多少种兑法.   Input 每行只有一个正整数N,N小于32768.   ...

  4. 一个Tomcat最多支持多少用户的并发?

    ,也就是说同时支持 另外,在 Java 中每开启一个线程需要耗用 1MB 的 JVM 内存空间用于作为线程栈之用.Tomcat的最大并发数是可以配置的,实际运用中,最大并发数与硬件性能和CPU数量都有 ...

  5. 基于sentry的前端错误监控日志系统(部署sentry服务器/前端项目部署)-让前端最快的定位到生产问题

    背景 在这越来越发达的网络时代,web应用也是越来越复杂,尤其是前端的开发,也是越来越受重视. 所以在我们前端开发完成后,会有一些列的web应用的上线验证,如自测.QA测试.code review 等 ...

  6. weblogic线程阻塞性能调优(图解)

    转自:http://blog.csdn.net/z69183787/article/details/12647539 声明:出现这个问题有程序方面.网络方面.weblogic设置方面等等原因,此文章主 ...

  7. asp.net core 集成JWT(一)

    [什么是JWT] JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案. JWT的官网地址:https://jwt.io/ 通俗地来讲,JWT是能代表用户身份的令牌,可以使用JWT ...

  8. 理解Android进程创建流程(转)

    /frameworks/base/core/java/com/android/internal/os/ - ZygoteInit.java - ZygoteConnection.java - Runt ...

  9. Android手机中UID、PID作用及区别

    PID 指进程ID. PID是进程的身份标识,程序一旦运行,就会给应用分配一个独一无二的PID(ps:一个应用可能包含多个进程,每个进程有唯一的一个PID) 进程终止后PID会被系统收回,再次打开应用 ...

  10. Android开发之自己定义Spinner样式的效果实现(源码实现)

    android系统自带的Spinner样式是远远满足不了我们实际开发过程中对Spinner UI风格的要求,因此我们肯定须要为了切合整个应用的风格,改动我们的Spinner样式.系统给我们提供了两种常 ...