swift - 类和结构体


//** Classes and Structures **
//类和结构体的相同点
// - 储存属性
// - 函数和方法
// - 下标语法
// - 初始化自己的状态
// - 可以扩展方法
// - 尊从协议


// 类可以做到,结果提做不到的
// - 继承
// - 类型转化
// - Deinitializers 来释放一个实类
// - 实类可以被多次引用

// 使用结构体,不能被引用, 就只能被拷贝.

// 定义类 clasee
class SomeClassb{
    //类的一些定义
}

//定义结构体
struct SomeStructreb{
    //结构体 定义
}

struct Resolution{
    var width = 0
    var height = 0
}
//结构体有两个存储属性 width height

class VideoMode{
    var resolution = Resolution()
    var interlaced = false
    var frameRate = 0.0
    var name:String?
}
// 类有 5 个存储属性


//类和结构体实例
let someResolution = Resolution()
let someVideoMode = VideoMode()

//获取属性
// 通过点语法可以得到 属性值
print("The width of someResolution is \(someResolution.width)")
//The width of someResolution is 0
print("The width of someVideoMode is \(someVideoMode.resolution.width)")
//The width of someVideoMode is 0


// 用点语法给属性赋值
someVideoMode.resolution.width = 1200
print("The width of someVideoMode is now \(someVideoMode.resolution.width)")
//The width of someVideoMode is now 1200


// 初始化结构体属性值  类文件不能这样初始化
let vga = Resolution(width: 640, height: 480)


//结构体和枚举是值类型
// 当值类型被引用的时候, 会把这个值类型赋值一份赋值给变量或者常量或者方法
// swift 中 所有基本数据结构都是用结构体在幕后实现的
// 如:

let hd = Resolution(width: 1920, height: 1080)
var cinema = hd
// hd 是一个结构体
// cinema 也是一个结构体. 但是cinema 和 hd 不是同一个结构体, 只是他们的值相同而已.
//检验一下: 修改cinema width的值,打印cinema.width 和 hd.width
cinema.width = 2048
print("cinema is now \(cinema.width) pixels wide")
//cinema is now 2048 pixels wide
print("hd is still \(hd.width) pixels wide")
//hd is still 1920 pixels wide
// 这种特性同样适用于 枚举型


// 类是引用类型
// 引用类型和值类型不同, 把引用类型赋值给变量,常量,方法之后,并不复制这个值,大家都是引用同一个值.
// 如:
let tenEighty = VideoMode()//tenEighty 指向一个 VideoMode() 实类
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0

let alsoTenEighty = tenEighty//alsoTenEighty 指向同一个 VideoMode() 实类
alsoTenEighty.frameRate = 30.0// 修改 alsoTenEighty.frameRate 的值
// 打印 tenEighty  的frameRate 属性
print("The frameRate property of tenEighty is now \(tenEighty.frameRate)")
//The frameRate property of tenEighty is now 30.0
// 我们发现 这时候 tenEighty.frameRate 的值也变了.


//判断是否同一个类引用
// 是否是同一个实类引用 `===`
// 是否不是同一个实类引用 `!==`
if tenEighty === alsoTenEighty{
    print("tenEighty and alsoTenEighty refer to same VideoMode instance")
    //tenEighty and alsoTenEighty refer to same VideoMode instance
}

//使用结构体的情况
// - 包含简单的数据值关系
// - 当该数据类型在赋值时需要拷贝时
// - 该数据类型的属性在赋值的时候需要拷贝时
// - 该类型不需要从别的类型那继承属性


//Strings Arrays Dictionaries 的引用和拷贝
// swift中 String , Arrays Dictionaries 都是用结构体实现的. 所以 这些都是值类型, 在赋值时会拷贝这个值.
// 但是: NSString NSArray NSDictionary 都是引用类型. 不会拷贝实类



/****  属性 ****/
// 存储属性
struct FixedLengthRange{
    var firstValue:Int
    let length:Int
}
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
// 两个存储属性, 变量 firstValue 常量 length.
// 初始化设置 firstValue 之后还可以改变 firstValue的值, 但是常量 length 的值初始化之后不能再变
rangeOfThreeItems.firstValue = 6

//当结构体被申明为常量, 那么结构体的所有属性都不能更改
let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
//rangeOfFourItems.firstValue = 6 会报错 firstValue 不能更改
// 这个特性不适用于 引用类型


//懒存储(懒加载)属性
// 只有在你第一次使用这个属性的时候才去给这个属性赋值, 称为懒存储(加载)属性
// 懒加载属性 必须是 变量 var 修饰, 不能是let 修饰. 因为 let 修饰的常量在初始化开始前就已经设好值了.
class DataImporter{
    var fileName = "data.txt"
}

class DataManager {
    lazy var importer = DataImporter()
    var data = [String]()
}

let manager = DataManager()
manager.data.append("Some data")
manager.data.append("Some more data")
// 到现在为止, 属性importer 还没有创建

print(manager.importer.fileName)
// 这个时候 importer 开始被创建

// 当使用多线程获取懒加载属性, 并不能保证这个属性只加载一次,也就是说, 懒加载属性不是线程安全的

// 存储属性和实类变量


////  计算属性
struct Point {
    var x = 0.0, y = 0.0
}

struct Size{
    var width = 0.0, height = 0.0
}

struct Rect {
    var origin = Point()
    var size = Size()
    var center:Point{
        get {
            let centerX = origin.x + (size.width/2)
            let centerY = origin.y + (size.height/2)
            return Point(x: centerX, y: centerY)
        }
        
        set (newCenter)
        {
            origin.x = newCenter.x - (size.width/2)
            origin.y = newCenter.y - (size.height/2)
        }
    }
}

var square = Rect(origin: Point(x:0.0,y:0.0), size: Size(width: 10.0, height: 10.0))
let initialSquareCenter = square.center
square.center = Point(x: 15.0, y: 15.0)
print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
//square.origin is now at (10.0, 10.0)

//快速 setter 声明
// setter 时可以不用传入参数, 默认参数为 newValue
//如:
struct AlternativeRect{
    var origin = Point()
    var size = Size()
    var center:Point{
        get{
            let centerX = origin.x + (size.width/2)
            let centertY = origin.y + (size.width/2)
            return Point(x: centerX, y: centertY)
        }
        
        set{
            origin.x = newValue.x - (size.width/2)
            origin.y = newValue.y - (size.height/2)
        }
    }
}

// 只读计算属性
struct Cubodid{
    var width = 0.0, height = 0.0, depth = 0.0
    var volume:Double{
        return width * height * depth
    }
}

let fourByFiveByTwo = Cubodid(width: 4.0, height: 5.0, depth: 2.0)
//在初始化的时候  计算属性不会出现
print("the volume of fourByFiveBytwo is \(fourByFiveByTwo.volume)")
//the volume of fourByFiveBytwo is 40.0


//** 属性观察 **

class StepCounter{
    var totalSteps:Int = 0 {
        willSet(newTotalSteps){
            print("About to set totalSteps to \(newTotalSteps)")
        }
        didSet{
            if totalSteps > oldValue{
                print("Added \(totalSteps - oldValue) setps")
            }
        }
    }
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
stepCounter.totalSteps = 360
stepCounter.totalSteps = 896
//willSet(newValue) 这里的newValue 可以起任意名字
//didSet 可以不用传参数进去, 这里参数默认是oldValue



/*--------------------------------------------------*/
//类型属性语法 区别于实类属性
struct SomeStructure{
    static var storedTypeProperty = "Some value."
    static var computedTypeProrty:Int{
        return 1
    }
}

enum SomeEnumeration{
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty:Int{
        return 6
    }
}



class SomeClass{
    static var storedTypeProperty = "Some value"
    static var computedTypeProperty:Int{
        return 27
    }
    
    class var overrideableComputedTypeProperty:Int {
        return 107
    }
}

print(SomeStructure.storedTypeProperty)
SomeStructure.storedTypeProperty = "Another value."
print(SomeStructure.storedTypeProperty)
print(SomeEnumeration.computedTypeProperty)
print(SomeClass.computedTypeProperty)

//类属性:
// 值类型的类属性 用static 修饰类属性
// 引用类属性 用 class 和 static(= final class (不能被继承)) 修饰类属性
// 引用类属性 只能是计算属性, 不能为存储属性, 因为OC 中没有类属性这个概念,为了和OC统一,swfit也没有存储类属性.(后面的版本应该会加上存储属性)
/*--------------------------------------------------*/


struct AudioChannel{
    static let thresholdLevel = 10
    static var maxInputLevelForAllChannels = 0
    var currentLevel: Int = 0{
        didSet{
            if currentLevel>AudioChannel.thresholdLevel{
                currentLevel = AudioChannel.thresholdLevel
            }
            if currentLevel > AudioChannel.maxInputLevelForAllChannels{
                AudioChannel.maxInputLevelForAllChannels = currentLevel
            }
        }
    }
}

var leftChannel = AudioChannel()
var rightChannel = AudioChannel()
leftChannel.currentLevel = 7
print(leftChannel.currentLevel)//7
print(AudioChannel.maxInputLevelForAllChannels)//7

rightChannel.currentLevel = 11
print(rightChannel.currentLevel)//10
print(AudioChannel.maxInputLevelForAllChannels)//10

你可能感兴趣的:(swift - 类和结构体)