类和结构体

//
//  main.swift
//  类和结构体
//
//  Created by Goddog on 15/7/18.
//  Copyright © 2015年 Goddog. All rights reserved.
//

import Foundation

print("类和结构体高度相似,但是结构体不支持继承,不支持定义析构器,结构体是值类型而类是引用类型。只有类的实例才能被称为对象,枚举、结构体的实例只能被成为实例,不能称之为对象")

//MARK: - 定义结构体和类
/**
    类前面的修饰符可以是 private、internal、public、final,
    一个类中3种常见成员:构造器、属性、方法。
    class修饰的成员(类成员)不能访问没有class修饰的成员(实例成员)。
    如果没有为一个类提供,系统会为该类提供一个默认的,无参的构造器,如果自己提供则系统不会自动提供,
*/
//定义一个类
class Person
{
    //定义了两个存储属性
    var name: String = ""
    var age: Int = 0
    //定义了一个say方法
    func say(content: String)
    {
        print(content)
    }
}
/**
    结构体前的修饰符可以是private、internal、public,但是不能是final(不支持继承)
    如果没有为一个结构体提供,系统会为结构体类提供一个默认的,无参的构造器和一个初始化所有存储属性的构造器。
    如果自己定义的构造器和系统提供的构造器同时存在,则不能在类中直接定义构造器,可以考虑通过扩展来为类添加构造器,类一样。
*/
//定义结构体
struct Dog
{
    //定义了两个存储属性
    var name: String
    var age: Int
    //定义了一个run方法
    func run(){
        print("\(name)迅速的奔跑")
    }
}

//创建实例,创建实例的根本途径是构造器
//使用Person类定义一个Person类型的变量
var p: Person
p = Person()
//我们用这个
var person = Person()

/**
 class或static修饰的方法和属性,属于类的本身,必须通过类型来调用,没有用class或static修饰的方法和属性,属于该类的实例,必须用实例来调用
*/
//访问person的name存储属性,并赋值
p.name = "曹操"
//调用方法
p.say("挟天子以令天下")
print(p.name)

struct Size {
    var width = 0, height = 0
}
//结构体的无参构造器
var s = Size()      //貌似要初始化值才能调用,   var d = Dog()就报错了
var size = Size(width: 10, height: 20)
//结构体初始化了一个所有存储属性的构造器
var dog = Dog(name: "旺旺", age: 2)

//MARK: - 值类型与引用类型
//swift的类是引用类型,而枚举、结构体是值类型
var ps = Person()   //创建了一个Person实例,Person实例被赋值给ps变量
//以上产生两个东西:一个是p变量,一个是Person实例,Person实例包含两个存储属性,Swift会让引用变量指向这个实例,ps实际是一个地址值
//多个引用指向同一对象
var ps1 = ps
ps.name = "刘备"
ps1.name = "孙权"
print("ps1把指向的对象存储属性改变了,所以ps指向的存储属性也改变了:\(ps.name)")

//但是结构体就不同了,看下面
var s1 = Size()
s1.height = 1
var s2 = s1
s2.height = 2
print(s2.height)
print(s1.height)   //结果还是1,因为结构体是值的引用每次复制了一份出来了

//引用类型的比较(类)
//!==和===只能用于引用类型变量的比较,用于比较两个引用类型的变量是否指向同一个实例
print(ps1 === ps)  //true,指向同一对象
print(ps1 !== ps)

//print(s1 === s2)  //因为是结构体的值引用所以报错了
//如果是值类型的比较就要运算符的重载了,重载==、!=
func == (left: Size, right: Size) -> Bool
{
    //只有两个Size的name、age都相等, ==就可以返回true
    return left.height == right.height && left.width == left.height
}
func != (left: Size, right: Size) -> Bool
{
    return !(left == right)
}
print("这样就正确了,重载了: \(s1 == s2)")

//MARK: - self关键字
//self 关键字总是指向该方法的调用者,self代表调用该方法的实例
//构造器中的self代表该构造器正在初始化的实例,方法中的self代表该方法的调用者
//self的主要作用是一个方法访问同一个类的另一个方法或者属性
class Cat
{
    func jump()
    {
        print("跳")
    }
    func run()
    {
        var c = Cat()   //又创建了一个对象
        c.jump()
        print("跑")
    }
    func say()
    {
        self.jump()      //同一个对象,也可以省略self
        print("叫")
    }
}
var cat = Cat()
cat.run()
cat.say()

//在局部变量和存储属性重名的情况下,局部变量会隐藏存储属性。为了在方法中强行引用存储属性,可以用self区分
class Dinosaur
{
    //定义两个存储属性
    var name: String = ""
    var age: Int = 10000
    //显示定义带参数的构造器
    init(name: String, age: Int)
    {
        //当局部变量隐藏存储属性时,可以self调用该构造器的实例,这样为该构造器正在初始化的实例的存储属性赋值
        self.name = name
        self.age = age
    }
    //定义一个info方法
    func info()
    {
        print("名字:\(name), 年龄:\(age)")
    }
}
var dinosaur = Dinosaur(name: "恐龙", age: 100)
dinosaur.info()

//当self作为方法调用者的代表时,程序可以像方法普通变量一样来访问self,甚至可以把self当成方法的返回值
class ReturnSelf
{
    var age: Int = 0
    func grow() -> ReturnSelf
    {
        age++
        return self  //返回该方法的调用者
    }
}
var rt = ReturnSelf()
//连续调用同一个方法
rt.grow().grow().grow()
print("rt的属性值是:\(rt.age)")  //3


//MARK: - 类or结构体?
//满足如下一个或多个条件时,考虑使用结构体
/**
1.封装少量相关简单数据值
2.让实例在赋值活参数传递时会自动复制副本
3.无需继承另一个已有的类或被其他类型继承
*/
//大部分时间都用  类





Swift技术学习 https://www.itkc8.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值