首页 > 代码库 > Swift learn 5

Swift learn 5

// Playground - noun: a place where people can play

import UIKit

//结构体&类的使用
struct NewStruct {
    var name:String = "";
    var age:Int = 18;
}

class Person{
    var person:NewStruct = NewStruct(name: "MichaelZero", age: 20);
    
    var className:String?;
    
    var friendIds:[Int]?;
    
    init(className:String){
        self.className = className;
    }
}

var person0 = Person(className:"C1");
println("PName:\(person0.person.name)");

//如果能够判定两个常量或者变量是否引用同一个类实例将会很有帮助。为了达到这个目的,Swift 内建了两个恒等运算符

var person1 = person0;
if person0 === person1{
    println("this is a same class.");
}else{
    println("this is a not same class.");
}

//结构体实例总是通过值传递,类实例总是通过引用传递。这意味两者适用不同的任务。当你在考虑一个工程项目的数据构造和功能的时候,你需要决定每个数据构造是定义成类还是结构体。

//结构体的主要目的是用来封装少量相关简单数据值。
//有理由预计一个结构体实例在赋值或传递时,封装的数据将会被拷贝而不是被引用。
//任何在结构体中储存的值类型属性,也将会被拷贝,而不是被引用。
//结构体不需要去继承另一个已存在类型的属性或者行为。

//合适的结构体候选者包括:
//几何形状的大小,封装一个width属性和height属性,两者均为Double类型。
//一定范围内的路径,封装一个start属性和length属性,两者均为Int类型。
//三维坐标系内一点,封装x,y和z属性,三者均为Double类型。

struct StaticStr {
    var name:Int;
    let systemName:String;
}

//除存储属性外,类、结构体和枚举可以定义计算属性,计算属性不直接存储值,而是提供一个 getter 来获取值,一个可选的 setter 来间接设置其他属性或变量的值。
class ParamsCount{
    var x:Int = 10;
    var y:Int = 10;
    var (x0, y0):(Int, Int);
    
    init(){
        (x0, y0) = (0 , 0);
    }
    
    var pointLink:(Int , Int){
        get {
            let x_link = self.x - self.x0;
            let y_link = self.y - self.y0;
            
            return (x_link , y_link);
        }
        
        set(newPoint){
            self.x = newPoint.0;
            self.y = newPoint.1;
        }
    }
}

//计算中心点坐标
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)
println("square.origin is now at (\(square.origin.x), \(square.origin.y))");


//结构体和枚举是值类型。一般情况下,值类型的属性不能在它的实例方法中被修改。
//但是,如果你确实需要在某个具体的方法中修改结构体或者枚举的属性,你可以选择变异(mutating)这个方法,然后方法就可以从方法内部改变它的属性;并且它做的任何改变在方法结束时还会保留在原始结构中。方法还可以给它隐含的self属性赋值一个全新的实例,这个新实例在方法结束后将替换原来的实例。
struct PointS {
    var x = 0.0, y = 0.0
    mutating func moveByX(deltaX: Double, y deltaY: Double) {
        x += deltaX
        y += deltaY
    }
}
var somePoint = PointS(x: 1.0, y: 1.0)
somePoint.moveByX(2.0, y: 3.0)
println("The point is now at (\(somePoint.x), \(somePoint.y))");

struct PointN {
    var x = 0.0, y = 0.0
    mutating func moveByX(deltaX: Double, y deltaY: Double) {
        self = PointN(x: x + deltaX, y: y + deltaY)
    }
}

//实例方法是被类型的某个实例调用的方法。你也可以定义类型本身调用的方法,这种方法就叫做类型方法。声明类的类型方法,在方法的func关键字之前加上关键字class;声明结构体和枚举的类型方法,在方法的func关键字之前加上关键字static。
struct LevelTracker {
    static var highestUnlockedLevel = 1
    static func unlockLevel(level: Int) {
        if level > highestUnlockedLevel { highestUnlockedLevel = level }
    }
    static func levelIsUnlocked(level: Int) -> Bool {
        return level <= highestUnlockedLevel
    }
    var currentLevel = 1
    mutating func advanceToLevel(level: Int) -> Bool {
        if LevelTracker.levelIsUnlocked(level) {
            currentLevel = level
            return true
        } else {
            return false
        }
    }
}

class Player{
    var tracker = LevelTracker();
    let playerName : String;
    func completedLevel(level:Int){
        LevelTracker.unlockLevel(level+1);
        tracker.advanceToLevel(level+1);
    }
    
    init(name:String){
        playerName = name;
    }
}

var player = Player(name: "Zero");
player.completedLevel(1);
println("highest unlocked level is now \(LevelTracker.highestUnlockedLevel)");

player = Player(name: "Michael")
if player.tracker.advanceToLevel(6) {
    println("player is now on level 6");
} else {
    println("level 6 has not yet been unlocked");
}

//下标脚本允许你通过在实例后面的方括号中传入一个或者多个的索引值来对实例进行访问和赋值。语法类似于实例方法和计算型属性的混合。与定义实例方法类似,定义下标脚本使用subscript关键字,显式声明入参(一个或多个)和返回类型。
//这种是用于基于一个固定的数学公式
struct Times{
    let basicNum:Int;
    
    subscript(index:Int) -> String{
        return String.convertFromStringInterpolationSegment(index * basicNum);
    }
}

var times = Times(basicNum: 10);
println("testing Value\(times[5])");

//根据使用场景不同下标脚本也具有不同的含义。通常下标脚本是用来访问集合(collection),列表(list)或序列(sequence)中元素的快捷方式。你可以在你自己特定的类或结构体中自由的实现下标脚本来提供合适的功能。
struct Matrix {
    let rows: Int, columns: Int
    var grid: [Double]
    init(rows: Int, columns: Int) {
        self.rows = rows
        self.columns = columns
        grid = Array(count: rows * columns, repeatedValue: 0.0)
    }
    func indexIsValidForRow(row: Int, column: Int) -> Bool {
        return row >= 0 && row < rows && column >= 0 && column < columns
    }
    subscript(row: Int, column: Int) -> Double {
        get {
            assert(indexIsValidForRow(row, column: column), "Index out of range")
            return grid[(row * columns) + column]
        }
        set {
            assert(indexIsValidForRow(row, column: column), "Index out of range")
            grid[(row * columns) + column] = newValue
        }
    }
}

var matrix = Matrix(rows: 10, columns: 10);

matrix[0 , 0] = 10;

println("value\(matrix[0 , 0])");

Swift learn 5