As an object-oriented language, class is also a very important type of Swift. Let’s look at the next simple class

// A class in Swift may not inherit from any other base class, so that class is itself a base class
class Person {
    // Define attributes
    var name:String
    var height = 0.0
    // constructor method, note that a no-argument constructor is automatically created by default if no constructor is written
    init(name:String) {self.name = name
    }
	// Destructor method, called when the object is released, similar to ObjC's dealloc, note that there are no parentheses and arguments, cannot be called directly
    deinit{
        print("deinit...")}// Define object methods
    func showMessage(a){
        print("name=\(name),height=\(height)")}}// Create an object for the class
var p = Person(name: "Liuting")
p.height = 170.0
p.showMessage() // Result: name=Liuting,height=170.0
 
// Classes are reference types
var p2 = p
p2.name = "XiaoMing"
print(p.name) // Result: XiaoMing
P and p2 are different values, but refer to the same object
if p === p2 { 
    print("p===p2") //p is equivalent to p2, indicating that both refer to the same object
}
Copy the code

In Swift, the concept of member attributes is diluted and attributes are divided into two types:

  1. Stored attributes: Conceptually and defined, stored attributes are more like member variables in other languages, except that:
  • Can control read and write operations (varCan be read or written,letRead only)
  • Property changes through the property monitor (willSet,didSet)
  • Fast implementation of lazy loading (lazyModified)
  1. Calculate attributeThe evaluated property does not store a value directly, but provides itgetterTo get a value, or to usesetterTo set other properties indirectly.

###### The following is an example of using object attributes:

class Account {
    // Define storage properties, set default values, add property listeners
    var balance:Double = 0.0{
        // called when an assignment is about to be made
        willSet{
            // Note that changing the value of balance is final
            self.balance = 2.0
            //newValue indicates the newValue to be assigned, and calling the property inside the property monitor does not cause the monitor to loop
            print("Account.balance willSet,newValue=\(newValue),value=\ [self.balance)")}// call after assignment
        didSet{
            // Note that changing the value of balance is final
            self.balance = 3.0
            //oldValue represents an oldValue that has been assigned, and calling the property inside the property monitor does not cause the monitor to loop
            print("Account.balance didSet,oldValue=\(oldValue),value=\ [self.balance)")}}}class Person {
    //firstName, lastName, age are storage attributes
    var firstName:String The //var definition indicates that the storage property is readable and writable
    var lastName:String
    let age:Int //let definition indicates that the storage property is read-only

    // Lazy loading of attributes, initialized on first access
    lazy var account = Account(a)// Lazily loaded attributes in Swift are not necessarily object types, but can be primitive types

    //fullName is a calculated attribute. You cannot access the calculated attribute directly in get or set methods, otherwise it will cause circular calls
    var fullName:String{
        // Called when getting the calculated property
        get{
            return firstName + "." + lastName
        }
        // Called when the calculation property is set
        set{
            // newValue in the set method is the newValue to be assigned.
            let array = split(newValue, maxSplit: Int.max, 
                                allowEmptySlices: false, 
                                     isSeparator: {$0= ="."})
            if array.count= =2 {
                firstName = array[0]
                lastName = array[1]}}}// constructor method, note that a no-argument constructor is automatically created by default if no constructor is written
    init(firstName:String, lastName:String, age:Int) {self.firstName = firstName
        self.lastName = lastName
        self.age = age
    }
    // Define the method
    func showMessage(a){
        print("name=\ [self.fullName), the age =\ [self.age)")}}// Create an object
var p = Person(firstName: "Liu", lastName: "Ting", age:22)
p.showMessage() // Result: Liu.Ting, age=22
p.fullName = "Liu.HAHA" // Set the calculation properties
p.showMessage() // Result: name=Liu.HAHA, age=22

p.account.balance = 10
Balance willSet,newValue=10,value=2.0 Account.balance didSet,oldValue=0,value=3.0 */
print("p.account.balance=\(p.account.balance)") // Result: p.account.balance=3.0
Copy the code
  1. Computed properties do not store a value directly, but provide itgetterTo get a value, or to usesetterTo set other properties indirectly;
  1. lazyProperties must have initial values, they must be variables and not constants, because constants are determined before construction is completed;
  2. Properties stored before object methods are constructed must have values (except optional types), either variable or constant, that can be specified at property creation time or within the constructor;
  3. Setting a default value for a storage property does not cause a property monitor call (and assigning a value in a constructor does not cause a property monitor call). Setting a storage property externally causes a property monitor call;

###### In addition to the object attributes above, we can also define class attributes:

class Student {
    Static = static; // Static = static
    static var skin:Array<String> {// Only getters are defined, indicating that the calculated property is read-only
        get{
            return ["yellow"."white"."black"]}}}// Read the attributes of the class
for color in Student.skin {
    print(color)
}
Copy the code

######Swift class methods can be divided into the following categories:

  1. Constructor method
  • Default constructor method (overridden if there is a specified constructor method with arguments)
  • Specify the constructor method
  • Convenience constructor method
  1. Destructor method
  2. Object methods
  3. Class method

###### The following is an example of method use:

class Person {
    // Define attributes
    var name:String
    var height:Double
    var age = 0
    //1.2. Specify a constructor method. Note that if you do not write a constructor, a no-argument constructor is automatically created by default
    init(name:String, height:Double, age:Int) {self.name = name
        self.height = height
        self.age = age
    }
    //1.3. convenience constructor, which simplifies constructor implementation by calling the specified constructor, providing default values
    convenience init(name:String) {self.init(name:name, height:0.0, age:0)}//2. Destructor method, called when the object is released, note that this method has no parentheses, no arguments, cannot be called directly
    deinit{
        print("deinit...")}//3. Object methods
    func modifyInfoWithAge(age:Int, height:Double){
        self.age = age
        self.height = height
    }
    //4. Class methods
    class func showClassName(a){
        print("Class name is Person")}}// Create objects using the convenience constructor
var p = Person(name: "liuting")
// Call the object method
p.modifyInfoWithAge(22Height:170)
// Call the class method
Person.showClassName()
Copy the code
  1. In addition to the constructor and destructor methods, the default parameters of other methods except the first parameter is a local parameter, starting from the second parameter is both a local parameter and an external parameter. However, for functions, only the default parameters are both local and external by default; all other parameters are local.
  1. All arguments to the constructor are both external and local by default
  2. Only convenience constructor methods can call the specified constructor of the current class
  3. The specified constructor method with arguments overrides the call to the default constructor method with no arguments
  4. Before an object is released, it automatically calls its own destructor and then calls its parent’s destructor level by level

Subscript is a shortcut to access the collection. If our custom class has the collection type function, we can define the subscript to quickly access the property of the class. The subscript is defined by the keyword subscript.

class Record {
    // Define attributes, store is the internal storage structure of Record, here is the dictionary
    var store:[String:String]
    // Specify the constructor
    init(data:[String:String]) {self.store = data
    }
    // subscript script, the subscript index is integer (note that you can also implement getter only read-only subscript script)
    subscript(index:Int) - >String{
        get{
			// Get the dictionary value according to the Index integer Index after sorting the dictionary key
            var key = sorted(Array(self.store.keys))[index]
            return self.store[key]!
        }
        set{
			// Set the dictionary value according to the Index integer Index after sorting the dictionary key
            var key = sorted(Array(self.store.keys))[index]
            self.store[key] = newValue //newValue is used as an attribute}}// subscript the subscript is a string index
    subscript(key:String) - >String{
        get{
            return store[key]!
        }
        set{
            store[key] = newValue
        }
    }
}
// Create an object
var record = Record(data:["name":"liuting"."sex":"male"])
print("r[0]=\(record[0])") R [0]=liuting
record["sex"] = "female"
print(record["sex"]) // Result: female
Copy the code

Like ObjC, Swift is single-inherited (multiple protocols can be implemented, and the protocol comes later). Subclasses can call properties and methods of the parent class, override methods of the parent class, add property monitors, and even override read-only properties as read/write properties.

// Define a parent class
class Person {
    var firstName:String
	var lastName:String
    var age:Int = 0
    var fullName:String{
        get{
            return firstName + "" + lastName
        }
    }
    // Specify the constructor
    init(firstName:String,lastName:String) {self.firstName = firstName
        self.lastName = lastName
    }
    // Object method
    func showMessage(a){
        print("name=\ [self.fullName),age=\ [self.age)")}// Subclasses cannot be overridden by final declarations
    final func sayHello(a){
        print("hello world.")}}// Define subclasses
class Student: Person {
    Override attribute, add monitor to attribute, override keyword
    override var firstName:String{
        willSet{
            print("firstName willSet")}didSet{
            print("firstName didSet")}}// Add subclass attributes
    var score:Double
     
    // Subclasses specify that the constructor must call the parent constructor
    // The parent constructor must be called after the subclass store property is initialized
    init(firstName:String, lastName:String, score:Double) {self.score = score
        super.init(firstName: firstName, lastName: lastName)
    }
    // the convenience constructor
    convenience init() {self.init(firstName:"", lastName:"", score:0)}// Rewrite a read-only property as a writable property
    override var fullName:String{
        get{
            return super.fullName;
        }
        set{
            let array = split(newValue, maxSplit: Int.max, 
								allowEmptySlices: false, 
									 isSeparator: { $0= ="." })
            if array.count= =2 {
                firstName = array[0]
                lastName = array[1]}}}// Override object methods
    override func showMessage(a) {
        print("name=\ [self.fullName),age=\ [self.age),score=\ [self.score)")}}// Create a subclass object
var p = Student()
p.firstName = "liu"
p.showMessage() // Result: name=liu,age=0,score=0
p.fullName = "Liu.Ting"
p.showMessage() // Result: name=Liu.Ting,age=0,score=0
p.sayHello()
Copy the code
  1. A constructor of a parent class can only be called if the constructor is specified.
  1. If a specified constructor with arguments exists in the parent class, the specified constructor of a subclass does not automatically call the specified constructor with no arguments in the parent class.
  2. If the parent class has only one no-argument constructor (whether or not it contains a convenience constructor), the constructor of the subclass automatically calls the no-argument constructor of the parent class by default (in which case you don’t need to call it manually).
  3. A constant property can only be initialized in the constructor of the class that defines it, not in a subclass
  4. Before an object is released, it automatically calls its own destructor and then calls its parent’s destructor level by level.
  5. A convenience constructor must call another specified constructor in the same class (either the specified constructor or the convenience constructor), and cannot call its parent constructor directly.

If you have any questions, please leave them in the comments below at #####! O (studying studying) O ha!