【学习】重学Swift5-面相对象、协议编程
六、面向对象编程
常见高阶函数
// map
print(numbers.map { $0 * 10})
// filter
print(numbers.filter{ $0 > 4 })
// reduce
print(numbers.reduce(10) { $0 + $1 })
// flatMap
print(arrayNumber.flatMap{ $0.map { $0 * 10}})
// compactMap
let names:[String?] = ["zhangsn", "lsi", nil, "wangwu", nil , "zhaoliu"]
print(names.count)
print(names.compactMap{$0})
print(names.compactMap{$0?.count})
print(names.count)
函数式编程
// 命令式编程风格常常迫使我们处于性能考虑,把不同的任务交织起来,以便能够一次循环来完成多个任务。
// 函数式编程用map()、filter()这些高阶函数把我们解放出来,让我们站在更高的抽象层次上去考虑问题,把问题看的更清楚。 // 简洁
// 面向对象编程通过封装不确定因素来使代码能被人理解;函数式编程通过尽量减少不确定因素来使代码被人理解
// 在面向对象的命令式编程语言中,重用的单元是类和类之间沟通用的消息。
// 函数式编程提倡在有限的几种关键数据结构(list、set、map)上运用针对这些数据结构高度优化过的操作,以此构成基本的运转机构。开发者在根据具体用途,插入自己的数据结构和高阶函数去调整机构的运转方式。 // filter 筛选 map 映射 foldleft/reduce 折叠/化约 // 面向对象编程三大特性:继承、封装、多态
枚举
// 首字母大写,给枚举类型起一个单数的名字
enum CompassPoint {
case north
case south
case east
case west
} enum Plant {
case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
} // 使用switch来匹配枚举值
let direction = CompassPoint.east
switch direction {
case .north:
print("north")
case .east:
print("east")
case .west:
print("west")
case .south:
print("south")
} // 遍历枚举的case 但是 枚举要遵循CaseIterable 协议
enum CompassPoint: CaseIterable {
case north
case south
case east
case west
}
let numbers = CompassPoint.allCases.count
for dir in CompassPoint.allCases {
print(dir)
} // 关联值
enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
} var productCode = Barcode.upc(8, 99, 434, 4)
print(productCode)
productCode = .qrCode("ddekideoded") switch productCode {
case .upc(let num1, let num2, let num3, let num4):
print("UPC:\(num1),\(num2),\(num3),\(num4)")
case .qrCode(let codeStr):
print("QRCode:\(codeStr)")
} // 设定原始值
enum ASCIIControlCharacter: Character {
case tab = "\t"
case lineFeed = "\n"
case caeeiageReturn = "\r"
}
print(ASCIIControlCharacter.tab.rawValue)
// 预设原始值
enum Plant: Int {
case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}
enum CompassPoint: String {
case north
case south
case east
case west
}
上面的两个 中第一个行星枚举的默认会比之前的自动加1,第二个方向枚举默认是同名字符串 let possiblePlant = Plant(rawValue: 7) // 递归枚举
indirect enum ArithmeticExpression {
case number(Int)
case addition(ArithmeticExpression, ArithmeticExpression)
case multiplication(ArithmeticExpression, ArithmeticExpression)
} let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)
let mul = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))
类、枚举、结构体添加属性
//
struct Point {
var x = 0
var y = 0
} struct Size {
var width = 0
var height = 0
} struct Rect {
var origin: Point
var size: Size var center: Point {
get {
// return Point.init(x: origin.x + size.width/2, y: origin.y + size.height/2)
Point(x: origin.x + size.width/2, y: origin.y + size.height/2)
} // set(newCenter) {
// origin.x = newCenter.x - size.width/2
// origin.y = newCenter.y - size.height/2
// }
set {
origin.x = newValue.x - size.width/2
origin.y = newValue.y - size.height/2
}
}
} var rect = Rect(origin: Point(x: 10, y: 10), size: Size(width: 10, height: 10))
print(rect.center) rect.center = Point(x: 12, y: 12)
print(rect.origin) // 属性观察者
class StepCounter {
var totalSteps: Int = 0 {
// willSet(newStep) {
// print("will set step \(newStep)")
// } willSet {
print("will set step \(newValue)")
} // didSet(oldStep) {
// print("did set step \(oldStep)")
// }
didSet {
print("did set step \(oldValue)")
}
} } var counter = StepCounter()
counter.totalSteps = 100
counter.totalSteps = 200
// 全局变量
var count: Int = 0 {
willSet {
print("will set count \(newValue)")
} didSet {
print("did set count \(oldValue)")
}
}
count = 10
为类、结构体、枚举添加方法
struct Point {
var x = 0
var y = 0 // 实例方法
func printInfo() {
print("x = \(x), y = \(y)")
} mutating func moveBy(x: Int, y:Int) {
self.x += x
self.y += y
} mutating func move2By(movex:Int, movey:Int) {
x += movex
y += movey
} // 类方法
static func printTypeInfo() {
print("a point")
}
} var p = Point(x: 10, y: 10)
p.printInfo() p.moveBy(x: 20, y: 20)
p.printInfo() p.move2By(movex: 12, movey: 12)
p.printInfo() Point.printTypeInfo()
类、结构体、枚举添加下标
struct MAtrix {
let rows: Int
let columns: Int var grid: [Double] init(rows: Int, colums: Int) {
self.rows = rows
self.columns = colums grid = Array(repeating: 0.0, count: rows * colums)
} subscript(row: Int, column: Int) -> Double {
get {
return grid[row * columns + column]
} set {
grid[row * columns + column] = newValue
}
}
} var matrix = MAtrix(rows: 2, colums: 3)
matrix[1, 0] = 9.0
print(matrix.grid) enum CompassPoint: Int {
case north = 1
case south
case east
case west static subscript(index: Int) -> CompassPoint{
get {
return CompassPoint(rawValue: index)!
}
}
}
let direction = CompassPoint[2]
类、结构体的初始化
struct Fahehrit {
var temperature = 32.0
}
struct Fahehrit {
var temperature: Double
init() {
temperature = 32.0
}
}
// s上面两个 含义一致 class ShoppingListItem {
var mame: String?
var quantity = 1
var purchased = false
}
// Swift为所有没有提供初始化器的结构体或类提供了默认的一个初始化器为所有属性提供了默认值
var item = ShoppingListItem() // 自定义的初始化
struct Celsius {
var tempertatureInCelsius: Double
init(fromeTahrenheit fathrenheit: Double) {
tempertatureInCelsius = (fathrenheit - 32.0) / 1.8
} init(fromeKelvin kelvin: Double) {
tempertatureInCelsius = kelvin - 273.15
}
} let n = Celsius.init(fromeTahrenheit: 212)
let b = Celsius.init(fromeKelvin:: 273) // 值类型的初始化器委托
struct Rect {
var origin = Point()
var size = Size() init()
init(origin: Point, size: Size) {
self.origin = origin
self.size = size
}
init(center:Point, size: Size) {
let originX = center.x - (size.width/2)
let originY = center.y - (size.height/2) self.init(origin: Point.init(x: originX, y: originY), size: size)
}
} // 类的继承和初始化
/*
所有类的存储属性(包括从它的父类继承的所有属性)都必须在初始化期间分配初始值
指定初始化器是类的主要初始化器。指定的初始化器可以初始化所有这个类引用的刷新并且调用合适的父类初始化器来继续这个初始化过程给父类链。
类偏向于少量指定初始化器,并且一个类通常只有一个指定初始化器。指定初始化器是初始化开始并持续初始化过程到父类链的“传送”点。
每个类至少有一个指定初始化器。
便捷初始化器是次要的。
*/
/*
指定初始化器必须从它的直系父类调用指定初始化器
便捷初始化器必须从相同的类里调用另一个初始化器
便捷初始化器最终必须调用一个指定初始化器
*/
class Person {
var name: String
var age:Int init(name: String, age: Int) {
self.name = name
self.age = age
} convenience init() {
self.init(name: "unNamed", age: 0)
} convenience init(age: Int) {
self.init(name: "unName", age: age)
}
} class Teacher: Person {
var salary: Int override init(name: String, age: Int) {
self.salary = 5000
super.init(name: name, age: age)
} init(name: String, age: Int, salary: Int) {
// 指定初始化器必须保证在向上委托给父类初始化器之前,其所在类引入的所有属性都要初始化完成。
// 所以salary初始化在前
self.salary = salary
super.init(name: name, age: age) // 初始化器在第一阶段初始化完成之前,不能调用任何实例方法、不能读取任何实例属性的值,也 不能引用 self 作为值。
self.test() // 指定初始化器必须先向上委托父类初始化器,然后才能为继承的属性设置新值。如果不这样做, 指定初始化器赋予的新值将被父类中的初始化器所覆盖。
// 所以父类继承来的name要在初始化后重新赋值
self.name = self.name + "老师"
} convenience init(salary: Int) {
self.init(name: "unNamed", age: 0, salary: 0)
// 便捷初始化器必须先委托同类中的其它初始化器,然后再为任意属性赋新值(包括同类里定义的 属性)。如果没这么做,便捷构初始化器赋予的新值将被自己类中其它指定初始化器所覆盖。
self.salary = salary + 100
} func test() {
print("Dddddd")
} deinit { }
} // 必要初始化器
class Person {
var name: String
var age:Int required init(name: String, age: Int) {
self.name = name
self.age = age
} convenience init() {
self.init(name: "unNamed", age: 0)
} convenience init(age: Int) {
self.init(name: "unName", age: age)
}
} class Teacher: Person {
var salary: Int required init(name: String, age: Int) {
self.salary = 5000
super.init(name: name, age: age)
} init(name: String, age: Int, salary: Int) {
// 指定初始化器必须保证在向上委托给父类初始化器之前,其所在类引入的所有属性都要初始化完成。
// 所以salary初始化在前
self.salary = salary
super.init(name: name, age: age) // 初始化器在第一阶段初始化完成之前,不能调用任何实例方法、不能读取任何实例属性的值,也 不能引用 self 作为值。
self.test() // 指定初始化器必须先向上委托父类初始化器,然后才能为继承的属性设置新值。如果不这样做, 指定初始化器赋予的新值将被父类中的初始化器所覆盖。
// 所以父类继承来的name要在初始化后重新赋值
self.name = self.name + "老师"
} convenience init(salary: Int) {
self.init(name: "unNamed", age: 0, salary: 0)
// 便捷初始化器必须先委托同类中的其它初始化器,然后再为任意属性赋新值(包括同类里定义的 属性)。如果没这么做,便捷构初始化器赋予的新值将被自己类中其它指定初始化器所覆盖。
self.salary = salary + 100
} func test() {
print("Dddddd")
} deinit { }
} // 可失败初始化
class Person {
var name: String
var age:Int init?(name: String, age: Int) {
if age > 200 {
return nil
}
self.name = name
self.age = age
} }
继承
class Vehicle {
var currentSepeed: Int = 0 var desc: String {
return "run at speed \(currentSepeed)"
}
// 不可重写
final var descStr: String {
return "run at speed \(currentSepeed)"
} func makeNoise() { }
} class Car: Vehicle {
var gear: Int = 0 override var desc: String {
return super.desc + " at gear \(gear)"
}
}
多态和类型转换
class MediaItem {
var name: String
init(name: String) {
self.name = name
}
} class Movie: MediaItem {
var director: String
init(name: String, director: String) {
self.director = director
super.init(name: name)
}
} class Song: MediaItem {
var artist: String
init(name: String, artist: String) {
self.artist = artist
super.init(name: name)
}
} let librarys = [
Movie.init(name: "movie1", director: "director1"),
Movie.init(name: "movie2", director: "director2"),
Song.init(name: "Song", artist: "art")
] let movies = [
Movie.init(name: "movie1", director: "director1"),
Movie.init(name: "movie2", director: "director2"),
] print(type(of: librarys))
print(type(of: movies)) for item in librarys {
if let realItem = item as? Movie {
print(realItem.director)
}
}
扩展
// extension的能力
1.添加计算实例属性和计算类型属性
2.定义实例方法和类型方法
3.提供新初始化器
4.定义下标
5.定义和使用新内嵌类型
6.使现有的类型遵循某协议
7.扩展可以向一个类型添加新的方法,但是不能重写一有的方法 // 添加属性
extension Double {
var km: Double {
return self / 1000.0
}
}
let speed: Double = 3400.0
print(speed.km)
// 添加方法
extension Int {
func repeatTask(task:() -> ()) {
for _ in 0..<self {
task()
}
}
}
3.repeatTask {
print("task ")
}
// 添加下标
extension Int {
subscript(digitIndex: Int) -> Int {
get {
var base = 1 for _ in 0..<digitIndex {
base *= 10
}
return (self / base) % 10
}
}
}
print(134[0])
// 添加内嵌类型
extension Int {
enum Kind {
case zero
case negative
case positive
}
var kind: Kind {
get {
switch self {
case 0:
return .zero
case let x where x > 0:
return .positive
default:
return .negative
}
}
}
}
print(0.kind)
协议
// 协议可以要求所有遵循该协议的类型提供特定名字和类型的实例属性或类型属性。协议并不会具体说明属性是储存型属性还是计算型属性--它只具体要求属性有特定的名称和类型。协议同时要求一个属性必须明确事可读的或可读的和可写的。 protocol SomeProtocol {
var mustBeSettable : Int {get set}
var doesNotNeedToBeSettable : Int {get}
} protocol FullyName {
var fullName: String { get }
} protocol Age {
var age: Int { get }
} struct Person: FullyName {
var fullName: String
}
let john = Person.init(fullName: "John Appless") class Starship: FullyName { var prefix: String?
var name: String init(name: String, prefix: String? = nil) {
self.name = name
self.prefix = prefix
} var fullName: String {
return (prefix != nil ? prefix! + " " : "")
}
} var ncc1701 = Starship.init(name: "Enter", prefix: "USS") struct People: FullyName, Age {
var fullName: String
var age: Int
} let p = People.init(fullName: "zhangsan", age: 30) func wish(to: FullyName & Age) {
print("name \(to.fullName) age \(to.age)")
} wish(to: p)
协议和扩展混合
protocol Name {
var name: String { get }
} protocol Age {
var age: Int { get }
} protocol TextRepresentable {
var desc: String { get }
} struct Person: Name, Age {
var name: String
var age: Int
} extension Person: TextRepresentable {
var desc: String {
return "name \(name) age \(age)"
}
} let p = Person.init(name: "tom", age: 33)
print(p.desc) extension Array: TextRepresentable where Element: TextRepresentable {
var desc: String {
let itemDesc = self.map{$0.desc}
return itemDesc.joined(separator: ",")
}
} let array1:[Int] = []
// print(array1.desc) 没有这个属性
let array2 = [Person.init(name: "zhangsna", age: 20), Person.init(name: "lisi", age: 44)]
print(array2.desc)
let array3 = [3, 5]
//print(array3.desc) 没有这个属性
let array4: [Any] = [Person.init(name: "zhangsna", age: 20), 3, Person.init(name: "lisi", age: 44)]
//print(array4.desc) 没有这个属性 // 为协议添加扩展
extension Collection where Iterator.Element: TextRepresentable {
var desc: String {
let itemDesc = self.map{$0.desc}
return itemDesc.joined(separator: ",")
}
} let array1:[Int] = []
// print(array1.desc) 没有这个属性
let array2 = [Person.init(name: "zhangsna", age: 20), Person.init(name: "lisi", age: 44)]
print(array2.desc)
let array3 = [3, 5]
//print(array3.desc) 没有这个属性
let array4: [Any] = [Person.init(name: "zhangsna", age: 20), 3, Person.init(name: "lisi", age: 44)]
//print(array4.desc) 没有这个属性面向协议编程
// OOP的缺陷
1.继承机制要求你在开始之前就能设计好整个程序的框架、结构、事物间的连接关系。
2.结构天生对改动有抵抗特性。
3.很多语言不提供多继承
4.OOP带来的可变、不确定、复杂等特征与并行编程中倡导的小型化、核心化、高效化完全背离 // POP // OOP主要关心对象是什么 POP主要关心对象做什么
【学习】重学Swift5-面相对象、协议编程的更多相关文章
- (8/18)重学Standford_iOS7开发_协议、block、动画_课程笔记
第八课: 1.协议 另一种安全处理id类型的方式如:id <MyProtocol> obj a.声明 //协议一般放于.h文件中或者在类的.h文件中 @protocol Foo <X ...
- 重学 以太网的mac协议的CSMA/CD
之前上课一直模糊的CSMA/CD进行系统性整理. CSMA/CD (Carrier Sense Multiple Acess/Collision Detect)应用在OSI的 数据链路层 在以太网中, ...
- JavaSE入门学习12: Java面相对象之static使用方法
我们能够基于一个类创建多个该类的对象,每一个对象都拥有自己的成员,互相独立. 然而在某些时候,我们更希 望该类全部的对象共享同一个成员. 此时就是static大显身手的时候了. Java中被stati ...
- 重学C++ (十一) OOP面向对象编程(2)
转换与继承 本节主要须要区分的是: 基类和派生类的转换: 引用(指针)的转换和对象的转换. 1.每一个派生类对象包括一个基类部分.因此.能够像使用基类对象一样在派生类对象上执行操作. 基于这一点,能够 ...
- 文成小盆友python-num7 -常用模块补充 ,python 牛逼的面相对象
本篇内容: 常用模块的补充 python面相对象 一.常用模块补充 1.configparser模块 configparser 用于处理特定格式的文件,起内部是调用open()来实现的,他的使用场景是 ...
- python 的面相对象编程--对应c++
在python的面相对象编程中,我们常常在class中可以看到a(), _b() , __c(), __d()__这样的函数. 由于我是看廖雪峰老师的教程,廖老师为了简单起见,没有引入太多概念,我 ...
- 重学前端--js是面向对象还是基于对象?
重学前端-面向对象 跟着winter老师一起,重新认识前端的知识框架 js面向对象或基于对象编程 以前感觉这两个在本质上没有什么区别,面向对象和基于对象都是对一个抽象的对象拥有一系列的行为和状态,本质 ...
- 201871010101-陈来弟《面相对象程序设计(java)》第十周学习总结
201871010101-陈来弟<面相对象程序设计(java)>第十周学习总结 实验八异常.断言与日志 实验时间 2019-11-1 1.实验目的与要求 (1) 掌握java异常处理技术: ...
- 五分钟学Java:如何学习Java面试必考的网络编程
原创声明 本文作者:黄小斜 转载请务必在文章开头注明出处和作者. 本文思维导图 简介 Java作为一门后端语言,对于网络编程的支持是必不可少的,但是,作为一个经常CRUD的Java工程师,很多时候都不 ...
- js编程-面相对象
//js面相对象编程 //定义constructor构造方法 function myFn(name,sex){ this.name = name; this.sex = sex; } //用proto ...
随机推荐
- 故障处理:ORA-04031真实案例分享
我们的文章会在微信公众号IT民工的龙马人生和博客网站( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢! 由于博客中有大量代码,通过页面浏览效 ...
- C# DES (cbc) 加密解密 (最简单的加密解密)
https://www.cnblogs.com/tianma3798/p/8807906.html 感谢这位大哥的代码提示 微软官网的这个示例正的是该换了,一点用处没看出来 https://docs. ...
- 安装程序无法自动安装virtual machine
安装VMware Tools 失败 发现在给过旧的系统安装 安装VMware Tools 的时候,会失败,比如 win7.win server2008等. 原因 官网的说明,在这里 看不懂的自行翻译: ...
- react中设置短链接
原因比如,我page要引入一个页面,那么引入起来就很麻烦.图片在src\assets\img\login\bg.jpg组件在src\pages\login\index.tsx引入代码如下: impor ...
- F407 中printf 的实现
装载 自 http://bbs.21ic.com/icview-860453-1-1.html 配置串口,利用printf函数输出字符,结果输出的还是ASCII码,这是为什么?难道是我的配置问题? ...
- 重新 开始 && ZCY
今天去见识了 淘宝的花名 好羡慕 这些 企业 活在了最好的时代 时代的宠儿. 千羽 见识了 高薪的优雅 衣食足而知荣辱 仓廪实而知礼节! 可能我会一辈子漂泊. 可是我想找到 我 ...
- python 格式修复
简介 使用工具yapf example yapf a.py
- java 打印程序堆栈中的信息
简介 作为程序奔溃调试的手段核心操作就是查看程序的堆栈. code package cn; import java.util.Scanner; public class StackTraceTest ...
- ABC397
最热泪盈眶的一次,中间被 D 卡了半小时,最后极限过 EF 翻盘. 不过 D 好像就是暴力,只是因为我没开 __int128?( rk.562. A - Thermometer 按照题意模拟即可. 点 ...
- 一文带你重新了解日事清:核心功能×企业背景×发展脉络x获奖情况
日事清产品简介 日事清是一款战略与执行一体化的企业管理平台,由北京创仕科锐信息技术有限公司研发推出.该平台具备成熟的"OKR目标管理-项目协同-流程配置-执行-绩效评估"闭环管理能 ...