Swift学习05(构造函数)
一、构造器(实例对象初始化方法)
“构造器在创建某个特定类型的新实例时被调用。
1、最简单的构造器:init()
“init() {
// 在此处执行构造过程
}”
class Student {
init() {
print("初始化一个实例对象会被调用")
}
}
let s = Student()
class Person :NSObject{
//有父类重写init()构造方法前必须加关键字 override
override init() {
print("初始化一个实例对象会被调用")
}
}
let p = Person()
新建一个Student1继承student重写init()
class Student {
init() {
print("初始化一个实例对象会被调用")
}
}
class Student1: Student{
//有父类重写init()构造方法前必须加关键字 override
override init() {
}
}
let s1 = Student1()
运行后观察控制台打印了一次,也就是let s1 = Student1()初始化是系统默认调用了 super.init()方法
class Person: NSObject{
var age :Int
override init() {
age=10
}
}
let p = Person()
print(p.age)
class Student :NSObject{
var age = 10;
}
let s = Student()
print(s.age)
2、默认构造器
“class ShoppingListItem {
var name: String?
var quantity = 1
var purchased = false
}
var item = ShoppingListItem()”
由于ShoppingListItem类中的所有属性都有默认值,也没有基类,将自动获得一个可以为所有属性设置默认值的默认构造器。然后通过调用这个默认构造器创造一个实例。
二、报错探究
- 例子一
class Person{
var sext = "男"
var age:Int = 26
}
class student: Person {
var name :String
init(name:String) {
}
}
错误:error: property 'self.name' not initialized at implicitly generated super.init call。在调用父类初始化时时,name属性没有被初始化。再次证明了以上两点:1.类在创建实例时,必须为所有存储型属性设置合适的初始值2.super.init()即时在构造器不主动调用,系统也会默认调用super.init()
解释:指定构造器必须保证它所在类引入的所有属性都必须先初始化完成,之后才能将其它构造任务向上代理给父类中的构造器。再次也说明了super.init()即时在构造器不主动调用,系统也会默认调用super.init()
纠正:
class Person{
var sext = "男"
var age:Int = 26
}
class student: Person {
var name :String
init(name:String) {
class Person{
var sext = "男"
var age:Int = 26
}
class student: Person {
var name :String
init(name:String) {
self.name = name//给属性赋值,完成初始化
//super.init() 系统会隐式调用,初始化父类
}
}
//子类只有在属性初始化完毕后才能继续初始化父类
- 例子二
class Person{
var sext = "男"
var age:Int = 26
}
class student: Person {
var name :String
init(name:String) {
self.name = name
self.age = 11
}
}
错误: error: use of 'self' in property access 'age' before super.init initializes self.父类还没有被初始化,就开始访问父类的属性。
解释:super.init默认会在即将构造完成时调用,而这里就相当于还没有开始初始化父类就开始访问父类的属性,这显然是不被允许的。
纠正:
classPerson{
varsext="男"
varage:Int=26
}
classstudent:Person{
varname:String
init(name:String){
self.name=name
super.init()
self.age=11
}
}
三、指定构造器和便利构造器
Swift 为类类型提供了两种构造器来确保实例中所有存储型属性都能获得初始值,它们分别是指定构造器和便利构造器。
指定构造器是类中最主要的构造器。一个指定构造器将初始化类中提供的所有属性,并根据父类链往上调用父类的构造器来实现父类的初始化。
1、指定构造器(Initialization)
class Student{
var name:String = "jack"
// init() {
// print("执行构造过程")
// }
}
let s = Student()
print(s.name)
/*
任何类都有一个默认的指定构造器,在新实例可用前必须执行这个过程完成一些初始化准备工作;init()就是系统默认的一个构造函数, Student()本质就是类调用系统的指定构造函数产生一个新事例对象。
*/
//默认指定构造器
class Person{
var age:String?
init() {/
//super.init()//调用父类的构造函数,可以不写系统会隐式调用
}
}
class Hospital:NSObject{
var name:String//定义属性
var age:Int
override init() {
self.name = ""//属性也可以在构造过程中再赋值
self.age = 0
}
}
var hospital = Hospital.init()
hospital.name = "张三"
//自定义指定构造器
class Teacher{
var age:String?
var name:String?
init(age:String,name:String) {
self.age=age;
self.name=name;
}
}
let teacher = Teacher.init(age: "14", name: "josn")
//Teacher()创建则会报错
if let name = teacher.name{
print(name)
}
//如果自定义了指定构造器,系统默认的构造器将被覆盖,新实例只能通过自定义的指定构造器创建
2、便利构造器(convenience Initialization)
convenience initializers是对类初始化方法的补充,用于为类提供一些快捷的初始化方法,可以不创建这类方法.一旦创建必须满足
:
(1)一个便利构造器构造器必须调用同一类中定义的其它构造器(便利构造器中仍然可以调用另一个便利构造器,这是没有问题的,但是最终都会去调用一个指定构造器。)
(2)便利构造器最终一定会调用到一个指定的构造器(也就是说实例的构建本质上还是在指定构造器中构建的,便利构造器没有构造实例的能力,需要最终依靠指定构造器)
//便利构造器
class student:NSObject{
var age:Int = 0
init(age:Int) {
self.age=age
super.init()//便利构造器最终一定会调用到一个指定的构造器
}
convenience init(value:Int) {//必须用convenience修饰
var value = value
value=value>18 ? 18:value
self.init(age: value)//须调用同一类中定义的其它构造器,不能用super.init()调用构造器,是不允许的。
}
}
let s = student(value: 20)
print(s.age)
print(s)
extension UIButton {
convenience init(title:String,backgroundcolor:UIColor) {
self.init()
setTitle(title, for:.normal)
self.backgroundColor = backgroundcolor
}
}
let button = UIButton(title:"title", backgroundcolor: .red)
//给系统类扩充一个方法
1.类方法
classfunccreateButton(imageName:String,bgImageName:String)->UIButton
{
//1.创建btn
letbtn=UIButton()
//2.设置btn的属性
btn.setImage(UIImage(named:imageName),forState:.Normal)
btn.setImage(UIImage(named:imageName+"_highlighted"),forState:.Highlighted)
btn.setBackgroundImage(UIImage(named:bgImageName),forState:.Normal)
btn.setBackgroundImage(UIImage(named:bgImageName+"_highlighted"),forState:.Highlighted)
btn.sizeToFit()
returnbtn
}
2、便利构造器(推荐使用)
extension UIBarButtonItem {
convenience init(imageName : String, highImageName : String = "") {
let btn = UIButton(type: .custom)
btn.setImage(UIImage(named: imageName), for: .normal)
btn.setImage(UIImage(named: highImageName), for: .highlighted)
self.init(customView: btn)
}
}
let butonitem = UIBarButtonItem(imageName: "imagname", highImageName: "hightname")