声 明
本教程仅用于初学SWIFT同学使用,内容由本人(孤狼)学习过程中笔记编写,本教程使用SWIFT版本为2.0。本教程内容可以自由转载,但必须同时附带本声明,或注明出处。PAEA.CN版权所有。
欢迎回到和屌丝一起学SWIFT系列教程,上节我们说了继承,这节我们来一起学习一个重要的东西-构造过程.构造过程是我们在使用类或结构体或枚举类型的时候必须要了解的一个知识.好了,废话不多说,开始吧.
构造过程
构造过程是类,结构体,枚举类型在实例化的时候的一个准备过程.只要你要实例化一个实例,那么这个过程是必须的步骤,我们可以把一些需要初始化的步骤放进来,来完善功能.
[构造器]
构造器是实例化一个类或结构体时被调用,我们可以在里面进行一些初始化动作.通过使用名称 init 来书写构造器.默认可以不用加入构造器,系统会自动使用默认的属性构造.
class A{
var a1=0;
init(){
self.a1=60;
}
}
var a=A();
print(a.a1);
//输出"60"
TIP:如果属性是固定值,那么构造器就没必要存在,因为这种初始化和直接设置默认值效果一样.
[定义构造过程]
通过使用构造器,我们可以自己来定义构造过程.我们通过给构造器传参的方式来控制构造器.同时,还可以定义多个构造器来实现更多的初始化功能.
单构造器
class Ren{
var name="";
var sex="";
init(sex:String){
self.sex=sex;
}
}
var nanRen=Ren(sex:"男");
var nvRen=Ren(sex:"女");
print(nanRen.sex); //输出"男"
print(nvRen.sex); //输出"女"
多构造器
class Ren{
var name="";
var sex="";
init(sex:String){
self.sex=sex;
}
init(name:String,sex:String){
self.name=name;
self.sex=sex;
}
}
var nanRen=Ren(name:"张三",sex:"男");
var nvRen=Ren(sex:"女");
print(nanRen.sex+nanRen.name); //输出"男张三"
print(nvRen.sex); //输出"女"
不带参数的构造器
上面的构造器在实例化的时候都要带上参数,比较麻烦,我们可以使用 _ 来设置不带参数.
class Ren{
var name="";
var sex="";
init(_ sex:String){
self.sex=sex;
}
init(_ name:String,_ sex:String){
self.name=name;
self.sex=sex;
}
}
var nanRen=Ren("张三","男");
var nvRen=Ren("女");
print(nanRen.sex+nanRen.name); //输出"男张三"
print(nvRen.sex); //输出"女"
在实例化过程中,常量也是可以修改的,但是仅限于没有值得常量.
class Ren{
let sex:String;
init(_ sex:String){
self.sex=sex;
}
}
var nanRen=Ren("男");
print(nanRen.sex); //输出"男"
[构造器代理]
既然构造器那么好,那么能不能自己调用自己来实现功能复用呢.当然可以,我们通过使用 self.init 来调用自身构造器,不过这里需要注意的是,类是不能直接使用这个方法的.仅支持结构体和枚举类型.
struct B{
var str="";
init(){}
init(str:String,name:String){
self.str=str+name;
}
init(name:String){
self.init(str:"你好,",name:name);
}
}
var b=B(name:"张三");
print(b.str);
//输出"你好,张三"
那么类要怎么来使用这么好的方法呢?很简单,就是在需要调用自身的构造器前加上关键字 convenience 就可以了
class C{
var str="";
init(){}
init(str:String,name:String){
self.str=str+name;
}
convenience init(name:String){
self.init(str:"你好,",name:name);
}
}
var c=C(name:"张三");
print(c.str);
//输出"你好,张三"
[构造器继承重写]
构造器可以被继承和重写,
class D{
var str="";
init(s:String){
str=s;
}
func out(){
print(str);
}
}
class E:D{
override init(s:String){
super.init(s:s);
str=s+"你好";
}
}
var e=E(s: "2016");
e.out();
//输出"2016你好"
TIP:在重写父类构造器的时候,要先使用 super.init() 来调用父类的构造器,这样是为了让父类初始化属性.
[可失败构造器]
如果用户不能按照规定使用构造器,那么我们可以设置可失败构造器.使用 init? 来定义构造器,就是一个可失败的构造器.
class F{
var str="";
init?(s:String){
if(s.isEmpty){
return nil; //只能返回空哦,这就是失败的.
}else{
self.str=s;
}
}
}
var f1=F(s:"");
print(f1?.str); //输出"nil"
var f2=F(s:"你好");
print(f2?.str); //输出"你好"
TIP:因为是可失败构造器,所以实例调用都会在实例后加 ? 来区别.
[必要构造器]
如果想让子类必须实现一个构造器,那就使用 required 来修饰这个构造器,让他成为必要构造器.同时,他的子类如果想重写这个构造器,也必须使用 required 关键字来修饰构造器,但是不需要加 override 关键字.
class G{
var str="";
required init(s:String){
str=s;
}
}
class H:G{
required init(s:String){
super.init(s:s);
str=s+"123";
}
}
var h=H(s: "你好");
print(h.str);
//输出"你好123"