swift面向對象基礎<二>

存儲屬性和計算屬性

今天討論實例存儲屬性與實例變量,結構體常量與實例屬性,定義計算屬性,setter方法,屬性觀察者

存儲屬性:存儲在類和結構體里的變量和常量。分為實例存儲屬性和類型存儲屬性,實例存儲屬性是指單個的實例,用來保存實例的狀態和數據。類型存儲屬性:屬于類型本身。類,結構體,枚舉都可以定義成類型存儲屬性。枚舉不可以定義成實例存儲屬性,

所有的存儲屬性都必須顯示的指定初始值,可以在定義時或者構造器中指定。
可選類型的存儲屬性是可以不指定初始值的
1.程序為所有的實例存儲屬性指定了初始值,且沒有構造器。則系統會提供2個構造器:一個無參數的構造器和一個初始化所有實例存儲屬性的構造器
2.屬性沒有初始值也沒有構造器,系統提供一個初始化所有屬性的構造器
3.有構造器,則要早構造器中為所有的屬性提供初始值
通過構造器函數完成對存儲屬性的初始化:

//存儲屬性
struct lengthrange{
    var start: Int
    //定義常量存儲屬性,可以不指定初始值
    let length: Int
}

var len = lengthrange(start: 9, length: 3)
print(len.start,len.length)
//定義一個結構體常量與她的實例屬性
struct lengthrange2{
  var start: Int
  var length: Int
}
let len2 = lengthrange(start: 1, length: 2)//不可以改變實例屬性

延遲存儲屬性:第一次調用的時候才會計算初始值的屬性,用lazy的修飾符
延遲存儲是一種延遲機制,只能聲明成變量。

計算屬性

計算屬性就相當于oc中的getter和setter方法合成的屬性,
計算屬性的格式:

/*
 [修飾符]var 計算屬性名:屬性類型{
 get {
 //get方法執行體,該方法一定要有返回值
 }
 set(形參名){
 set方法執行體,該方法一定不能有返回值
 }
 
 */

屬性觀察者:用來觀察屬性的變化的,為了讓屬性在被賦值的時候獲得執行代碼的機會
1.它可以監聽除了延遲屬性之外的所有存儲屬性(包括類型存儲屬性和實例存儲屬性)
2.可以通過重載的方式為繼承得到的屬性添加屬性觀察者

/*
 屬性觀察者:
 [修飾符]var 計算屬性名: 屬性類型 = 初始值{
 will set(newvalue){
 //屬性即將被賦值之前調用的方法
 }
 didset(oldvalue){
 //屬性被賦值完成之后自動調用的方法
 }
 willset和didset后面的參數都是可以省略的
 
 */
class user{
    var first: String = ""
    var last: String = ""
    //定義計算屬性
    var fullname: String{
        //定義計算屬性的getter方法,該方法的返回值有first,last兩個存儲屬性決定
        get{
            return first + "-" + last
        }
        //定義計算屬性的setter方法
        //該setter方法將負責改變該實例的first,last兩個存儲屬性
        set(newvalue){
            var names = newvalue.components(separatedBy: "-")
            self.first = names[0]
            self.last = names[1]
        }
    }
    init (first: String , last: String){
        self.first = first
        self.last = last
    }
    
}

let s = user(first: "swift", last: "hello")
print(s.fullname)//調用get方法
s.fullname = "hello-swift"http://調用setter方法
print(s.first)

//只讀屬性,不需要set部分,可以省略get和花括號
//屬性觀察者

class person {
    //定義存儲屬性
    var name: String = "" {
        willSet{
            if newValue.characters.count>6 || newValue.characters.count < 2 {
                print("你設置的人名不符合要求,請重新設置")
            } else{
            print("人名設置成功")
            }
        }
        didSet{
            print("人名設置完成,被修改的原名:\(oldValue)")
        }
    }
    var age : Int = 0{
        willSet{
            if newValue > 100 || newValue < 0 {
                print("設置的年齡\(newValue)不符合要求")
            } else{
                print("年齡設置成功!")
            }
        }
        didSet{
            print("年齡設置完成,被修改的年齡為\(oldValue)")
        }
    }
}

var p = person()
p.age = 999

p.age = 10//將會調用willset和didset方法

swift面相對象中的方法

在方法中,談論的是方法的所屬性,方法轉換為函數,方法的外部形參名,值類型的可變方法,屬性和方法的統一

1.定義方法需要在枚舉,結構體,類中定義,不能夠獨立的定義
2.方法可以使類型本身,也可以是屬于實例
3.不能獨立使用方法,需用類型或者實例充當調用者
4.枚舉和結構體中的方法用static修飾,類中用class修飾,都屬于類方法。否則屬于實例方法
//將方法轉換成函數

class someclass {
    func test() {
        print("==test 方法 ==")
    }
    class func bar(msg: String){
        print("== bar 類型方法==,傳入的參數:\(msg)")
    }
}

//創建實例
var sc = someclass()
//將sc的test方法分離成函數
var f1 : ()->() = sc.test//不能有(),()標示調用方法,沒有()標示賦值給f1,從而把方法轉變成了函數

//將sc的bar方法分離成函數
var f2:(String) -> Void = someclass.bar

//直接調用函數就等于調用了方法
f1() //等價于sc.text()
f2("swift")

方法的外部形參名

//方法的外部形參名
class person {
    
    var name: String
    
    init(name: String){
        self.name = name
    }
    
    func eat (food: String , drink: String , cigarette: String){//在方法名的前面添加“_”標示不需要外部參數名
        print("\(self.name)吃著\(food),喝著\(drink),抽著\(cigarette)")
    }
}
var p = person(name: "tom")
p.eat(food: "烤鴨", drink: "啤酒", cigarette: "雪茄")//swift默認會添加外部參數名,

值類型的可變方法

值類型代表的是結構體或者是枚舉,將mutating放在func之前,即將該方法聲明為可變方法

struct jkrect {
    var x: Int
    var y: Int
    var width: Int
    var height: Int
    mutating func movebyx(x: Int, y: Int) {
        self.x += x
        self.y += y
    }
}

//創建實例
var rect = jkrect(x: 20, y: 12, width: 200, height: 300)
//調用mutating方法,該方法可以改變rect實例的存儲屬性
rect.movebyx(x: 100, y: 90)
print("rect舉行的左上角的x坐標為:\(rect.x),y\(rect.y)")
//注意:常量類型的結構體,枚舉是不可變的

屬性和方法的統一

1.使用函數類型定義屬性,并將函數或者閉包作為該屬性的初始值,這個屬性就成了方法。

//屬性和方法的統一

func factorial(n: Int) -> Int{
    var result = 1
    for i in 1...n {
        result *= i
        
    }
    return result
}

struct somestruct {
    var info: () -> Void = {
        print("info方法")
    }
    //將全局函數作為fact存儲屬性的初始值
    static var fact: (Int) -> Int = factorial
}

var sc = somestruct()
//調用info方法
sc.info()

//使用閉包對sc對象發的info賦值,相當于重新定義sc的info方法
sc.info = {
    print("另外一個閉包")
}

sc.info()

var n = 6

//調用的fact方法,執行的是階乘
print("\(n)的階乘是:\(somestruct.fact(6))")
//使用閉包對somestruct的fact賦值,相當于重新定義somestruct的fact方法
somestruct.fact = {
    var result = 1
    for i in 1...$0{
        result += i
    }
    return result
}
//再次調用fact方法,執行的是累加
print("\(n)的累加的和")

下標
需要了解下標的用法和下標的重載

1.所有的swift類型(枚舉,類,結構體)都支持下標
2.同一個類型可以定義多個下標值
3.通過下標的形參列表或者返回值的類型來區分不同的下標
4.同一個類型中定義多個不同的下標,被稱為下標重載。

//下標的基本用法
/*
 Subscripe(形參列表) -> 下標返回值類型 {
 get {
 //get方法執行體,該方法一定有返回值
 }
 set (形參名){
 //setter方法執行體,該方法可以沒有返回值
 }
 
 }
 形參列表:與函數的形參列表的用法基本相同,但是不支持指定外部參數和默認值
 下標返回值類型:可以是任何有效的類型
 */
//下標
struct jkrect2 {
    var x: Int
    var y: Int
    var width: Int
    var height: Int
    
    //定義下標,指定下標只接受int類型的參數,下標返回類型為int
    subscript (index: Int) -> Int{
        //get部分
        get{
            switch(index){
            case 0:
                return self.x
            case 1:
                return self.y
            case 2:
                return self.width
            case 3:
                return self.height
            default:
                print("不支持該索引值")
                return 0
            }
        }
        //set部分
        set{
            switch(index){
            case 0:
                self.x = newValue
            case 1:
                self.y = newValue
            case 2:
                self.width = newValue
            case 3:
                self.height = newValue
            default:
                print("不支持該索引值")
            }
        }
        
        
    }
}

//創建實例
var rect2 = jkrect2(x: 20, y: 12, width: 200, height: 300)
//通過下標進行賦值
rect2[0]=40
rect2[1] = 67
//通過下標訪問rect中的函數
print("rect2矩形的x坐標\(rect2[0])y坐標為 \(rect2[1])")

//省略下標中的set部分即是只讀下標

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,716評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,706評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,036評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,203評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,725評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,451評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,677評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,857評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,407評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,643評論 2 380

推薦閱讀更多精彩內容