Swift枚举|结构体|类|属性|方法|下标脚本|继承
1. 枚举:
->在Swift中依然适用整数来标示枚举值,需搭配case关键字
enum Celebrity{ case DongXie,XiDu,Nandi,BeiGai } // 从左到右对应0,1,2,3
enum CompassPoint {
case North
case South
case East
case West
//enum中可以定义方法
func show(){
print(self)
}
}
//定义enum 变量
var p = CompassPoint.North
var p2 = CompassPoint.South
p.show()
p2.show()
var point:CompassPoint = .West
switch point{
case .North:
print("北")
case .South:
print("南")
case .East:
print("东")
case .West:
print("西")
}
enum Week:Int {
case Sun, Mon, Tur, Wen, Thu, Fri, Sat
}
//原始的(裸值)需要进行类型标注,
// notice:这里通过调用枚举类型 Week 调用 枚举成员Sun 裸值(及C中所述的枚举整型值),需要在赋值的变量后面加上的的类型标示符号
var weekDay:Int = Week.Sun.rawValue
//也可以直接通过Week的 rawValue方法调用得道当前的 枚举成员
var week:Week? = Week(rawValue:7) //这里如果rawValue 超出了枚举值的返回,则返回为空,所以week需要使用可选值来接收
//还可以利用元组特性设置关联的枚举成员
enum BarCode {
case UIPCA(Int,Int,Int) //条形码
case QRCode(String) //二维码
}
//定义个枚举变量
var barcode = BarCode.UPCA(690,3322323,2)
barcode = Bar.QRCode("http://fdsafdsfa.com")
switch barcode {
case BarCode.UPCA(let(num,id,check)):
print("这是一个条形码 \(num)-\(id)-\(check)")
case BarCode.QRCode(let string):
print("这是一个二维码 对应的字符串是:\(string)")
}
}
/**使用新的写法,在绑定变量的同时,指定条件判断,类似于SQL*/
switch aPoint {
//在绑定一个变量的同时,可以绑定x == y
case let(x,y) where x == y:
print("x 与 y相等斜线上 x = y")
case let(x,y) where x == -y:
print("x 与 -y斜线上 x = -y")
default:
print("other")
}
2. 结构体和类:
相同点:
结构题和类,都在定义一种类型
都可以在内部定义属性和方法
都可以定义下标运算符
都可以定义初始化方法(Int 初试化器, 构造器 构造方法)
都可以使用扩展现有的功能(OC中有分类,Swift中没有分类,叫扩展)
都可以遵循制定的协议
不同点:
类可以继承,结构体不能
类有多态,结构体没有
类的内存支持自动引用技术,结构体不支持引用技术,结构体变量都是在栈中分配内存空间,不需要手动管理
类是引用类型 结构体是值类型
//属性的初始化就提供了一个无参 和统一的初始化器
struct Resolution {
var width = 0.0
var height:Float = 0.0
}
//类中申明属性必须进行初始化,除非它是可选值
class VideoMode {
var resolution = Resolution()
var interlocaed = false
var frameRate = 0.0
var name:String?
}
//结构体是值类 类是引用类型
var res = Resolution()
var res2 = res
res.width = 1024
res2.width
var vmode = VideoMode()
var vmode2 = vmode
vmode.name = "zhanshang"
vmode2.name
/** ===比较地址是否相等*/
if vmode === vmode2 {
print("两个引用是同一个值")
}
if vmode2 !== vmode {
print("两个引用不是同一个地址")
}
/** 结构体的统一初始化器,这与C中的结构题嵌套非常相识,紧紧是指把变量的定义方式改变了一下,另外支持 点语法访问层级嵌套属性*/
struct Point {
var x :Float
var y :Float
}
struct Size {
var w :Float
var h :Float
}
struct Rect {
var origin: Point
var size: Size
}
var rect = Rect(origin: Point(x: 100, y:20), size: Size(w : 2 ,h: 3))
rect.size.w
rect.origin.x
3. 属性,在Swift中属性有两个分类方式
第一种方式:
/**
1. Swift中属性有两个分类方式
第一种方式:
-> 存储属性(Stored Properties):用变量或者常量来保存属性值
-> 计算属性(calculate Properties): 通过计算得来的。
举例:
出生日期: 存储树形 , 年龄:需要通过两个时间进行计算
-> 第二中分类方式:
实例属性 和 类型属性
*/
// 存储属性
struct MyRange {
var location:Int
let length:Int
}
var myRnage = MyRange(location: 0, length:100)
struct Point {
var x = 0.0, y = 0.0
}
struct Size {
var w = 0.0, h = 0.0
}
struct Rect {
//存储属性,使用变量或者常量来保存存储属性
var orign = Point() //创建 point对象
var size = Size()
var center: Point {
get{
let centerX = orign.x + size.w * 0.5
let centerY = orign.y + size.h * 0.5
return Point(x: centerX, y: centerY) //返回一个point类型
}
//这里如果没有参数 则使用默认的 newValue
set{
let newOrignX = newValue.x - size.w * 0.5
let newOrignY = newValue.y - size.h * 0.5
orign = Point(x: newOrignX, y: newOrignY) //实现origin的赋值
}
/* set(newCenter){
let newOriginX = newCenter.x - size.w * 0.5
let newOriginY = newCenter.y - size.h * 0.5
origin = Point(x: newOriginX, y: newOriginY)
} */
//假设做一个只读的计算属性
}
//如果只读计算属性,只有一行代码可以省略return
var center2:Point {
get {
return Point(x: 500 + 100,y: 100)
}
}
}
var rect = Rect(orign:Point(x: 0, y: 0), size: Size(w:300,h: 200))
rect.center.x
rect.center.y
rect.center = Point(x: 200, y: 200)
rect.orign.x
rect.orign.y
/** 延迟属性 类似 OC的懒加载,或者延迟加载*/
class DataImporter {
init(){
print("DataImporter create")
}
var fileName = "data.txt"
//这个需要用到的时候才去加载
}
class DataManager {
lazy var dataImporter = DataImporter()
}
//创建DataManager这个对象
var dataManager = DataManager()
/**在需要执行懒加载的属性前面加上layz*/
dataManager.dataImporter
4. 属性监视器:是一段代码,这段代码会在属性发生变化的时候自动调用
->计算属性,延迟属性,不能设置监视器,只有存存储属性才能设置监视器
->属性监视器,在属性初始化的时候不调用
->属性监视器有两种,willSet,didSet
class StepCounter {
var labelText = " text content"
/**storeage property*/
var a :Int = 10
//只读计算属性
var b:Int {
return 10
}
// 给属性 加属性监视器
var totalSteps:Int = 10 {
willSet (newValue){
print("属性将要变化时调用 要改变成\(newValue) 现在是\(totalSteps)")
}
didSet{
print("属性值已经发生改变了嗲用原来的值时\(oldValue)现在是\(totalSteps)")
labelText = "改变的值时\(totalSteps)"
}
}
}
var propertyName:Int = 10{ willSet(newValue){ //inserCode here } didSet{ //insertCode here } }
var stepCounter = StepCounter()
stepCounter.totalSteps = 50
stepCounter.labelText
stepCounter.totalSteps = 20
stepCounter.labelText
5. 类型属性:
在结构体或者枚举中,使用static修饰的属性以及在类中使用class关键字修饰的属性叫做类型属性,属于整个类和对象无关。
在struct 中定义的类型属性,可以是存储属性,也可以是计算属性
在class 中定义的类型属性,只能是计算属性(如果需要使用存储树形座位设计类型属性,可以加上static关键字)
struct SomeStrut {
//存储属性
var a = 10
//计算属性
var b:Int {
return 10
}
//类型属性
static var x = 10
static var y:Int {
return 10
}
}
var someStruct1 = SomeStrut()
someStruct1.a //10
var someStruct2 = SomeStrut()
someStruct2.a //10
SomeStrut.x //10
SomeStrut.y //10
class SomeClass {
var a = 10
var b :Int {
return 10
}
/** 类型属性,太奇葩了*/
static var y :Int {
return 100
}
class var x:Int {
return 100
}
static var storeagePorperty:Int = 10 //编译通过。优先使用static
// Swift编译无法通过❌class var storagePorperty1:Int = 100
}
SomeClass.y
SomeClass.storeagePorperty = 123
SomeClass.x
6.实例方法,类方法,几乎同OC一样
//实例方法 与类方法,类中的实例方法几乎和OC一样
/** 类类型的实例方法*/
class Counter{
var count = 0
func increment(){
count++
}
func incrementBy(amount: Int){
count += amount
}
func incrementBy(amount: Int ,numberOffTimes: Int) {
count += amount * numberOffTimes
}
}
/** create a instance */
var counter = Counter()
/** invoke instance method*/
counter.increment()
/** 值类型的实例方法 */
struct Point {
var x = 10, y = 10 //实例 值类型属性,由对象调用,或者对象 self指针调用
var z = 250
static var sx = 10 //类类型属性,由类调用,或者类 self指针调用
func show() {
print("点点\(x)")
Point.sx = 1111
}
//值类型的实例方法,默认不可以修改实例属性,如果非要修改则加上mutating
mutating func setX(px: Int,AndY y:Int) {
// x = px
self.x = px
//防止参数和属性重名
self.y = y
Point.sx = 111
}
}
enum StatusSwitch{
case Study,Dining,Review,Sleep
func show(){
switch self{
case .Study:
print("正在学习")
case .Dining:
print("正在吃饭")
case .Review:
print("正在复习")
case .Sleep:
print("正在睡觉")
}
}
/** 切换状态, 这里如果想修改self需要在前面加上 mutating*/
mutating func nextStatus(){
switch self {
case .Study:
print("下一步吃饭")
self = .Dining
case .Dining:
print("下一步 去复习")
self = .Review
case .Review:
print("下一步 去睡觉")
self = .Sleep
case .Sleep:
print("下一步 去学习")
self = .Study
}
}
}
var ss = StatusSwitch.Study
ss.show()
ss.nextStatus()
ss.nextStatus()
ss.nextStatus()
ss.nextStatus()
ss.nextStatus()
ss.nextStatus()
ss.nextStatus()
ss.nextStatus()
7. 类型方法:
//类型方法 和 OC中的类方法,含义相同
class SomeClass {
var prop:Int = 0 //实例属性必须要有了对象之后能方位
class var a:Int { //类属性 ,class也可以使用static
return 10
}
func instanceMethod() {
print("this is a instance method")
self.prop
SomeClass.a
//self.a a为类属性,所以无法调用
}
class func typeMethod(){ // class func 代表定义个类方法
print("这是一个类型方法")
//同OC,类方法中不能访问实例属性,但是可以访问类型属性
// self.prop
self.a //self带表调用这个方法的对象,self相当于调用类方法的对象,类对象
SomeClass.a
}
}
var p = SomeClass()
p.prop
SomeClass.a
//类方法的调用
SomeClass.typeMethod()
//先创建一个类的对象-》
var instanceObject = SomeClass() //类名+()可以创建一个类的对象
instanceObject.prop
instanceObject.prop = 10
instanceObject.prop
struct SomeStruct {
var prop:Int = 0
/**声明一个static的存储属性*/
static var a: Int = 0
func show(){}
func instanceMethod(){
//此处实例属性可以读但是不能修改 prop = 1000,如果需修改采用
self.show()
print(prop)
}
/**结构体中, 类方法使用static,在类中可以使用static和class定义类方法和变量方法, C++里面叫做静态方法,但是在结构体中只能是static */
static func typeMethod(){
print("这是一个类型方法")
//self.show() 实例方法,❌,此处无法使用
}
}
/**枚举中 类型方法*/
enum StatusSwitch {
case Study,Dinig,Review,Sleep
static func typeMethod() {
print("这是一个类型方法")
}
static func create()->StatusSwitch {
return self.Study //StatusSwitch 类对调用 create 类方法,self 指向StatusSwitch,所以返回为StatusSwitch类型
}
func show() {
print("这是一个实例方法")
}
}
StatusSwitch.create().show() //
StatusSwitch.Study.show() //与上面等价 //枚举成员可以调用枚举类的方法,这样理解会好记一点,搞不明白的就暂时当成一种格式来记,等代码积累量上去了再回过头来研究。
8. 下标脚本,主要用于检查数组边界是否越界;使用断言的方式
class MyArray {
//private 私有的,越界返回真,不越界返回假
pravate var array = [0,1,2,3,4,5,6,7,8,9]
func indexIsValid(index:Int) -Bool {
if index < 0 || index >array.count - 1 { return ture } else { return false }
/**增加数据*/
func addObjectAtIndex(index:Int ,object:Int) {
assert(indexIsValid(index))
array.insert(object,atIndex:Index)
}
func show(){ print(array) }
}
//让MyArray支持下标,写法一
定义一个 通过subscript构建一个整型的下标函数,创建set 和 get方法,其中set方法中newValue和数组赋值时,外界传入的形参
subscript(index:Int)->Int {
get { return array[index] }
set { array[index] = newValue }
}
方法二:通过改写set方法
subscript(index:Double)->Int {
get{ return array[Int(index + 0.5)]}
set{ array[Int(index + 0.5)] = newValue }
//此处的newValue为set方法调用时外部带的参数 类似于 (int)setnewValue:(int)newValue
}
var myArray = MyArray()
myArray.show()
myArray.addObjectAtIndex(1, object: 100)
myArray.show()
myArray.array + [30,300]
myArray.array.removeAtIndex(5)
myArray.show()
myArray.array[0]
9. 继承:
父类 子类 (基类,派生类)
Swift中的特点: 一个类可以没有父类,不像OC所有的类都继承于NSObject,Swift中是单即成类,一个类只能由一个父类,但是可以有多个子类。
class Vehicle {
//存储属性 storage properties
var currentSpeed = 0.0
//计算属性 calculate properties
var description:String {
return "当前速度是每小时\(currentSpeed)公里"
}
func makeNoise() {
print("父类发生的方法")
}
func show(){
print("父类显示的方法")
}
}
/** inheritance*/
class Bicycle: Vehicle {
/** extension propertie*/
var hasBasket = false
/** extension method*/
func test(){
print("subClass extension method")
}
/** override parent method*/
override func makeNoise() {
print("subClass dong dong ...")
}
}
var bike = Bicycle()
bike.show()
bike.makeNoise()
bike.hasBasket
bike.currentSpeed
/**父类型指向子类型,前面obj为交通对象,makeNoise重写后被覆盖,先调用子类的方法
*/
var obj:Vehicle = Bicycle()
obj.makeNoise()
}
/**
覆盖父类的方法只需要在方法前面使用override关键字, override func 。。。。
重写父类属性只需要在子类定义与父类相同的属性,并在后面加上{ didSet{ //inertCode 需要重写的内容 } }
在父类中 变量和方法前面只要加上 final关键字则表示该方法不能被重写
*/
class Car : Vehicle{
var gear = 1
// 重写覆盖父类的方法
override func makeNoise(){
print("汽车滴滴")
}
// 重写计算属性
override var description : String {
return super.description + "在\(gear)档上"
}
// 重写父类的存储属性
override var currentSpeed : Double{
didSet{
gear = Int(currentSpeed/10.0) + 1
}
}
}
var car = Car()
car.gear
car.currentSpeed = 40
car.description
car.gear
/*final */ class Base { // 限制这个类不能被继承
final var a = 10 // final 不能被重写
final func show(){ } //final 的方法不能被重写
}
class Child: Base {
}
// 开发中还有一种常见的形式 组合
class Radio{
var price : Double = 0.0
func radio(){
print("收听广播")
}
}
class MyCar{
var radio = Radio()
}
var mc = MyCar()
mc.radio.radio()
mc.radio.price = 10000000