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:
- Stored attributes: Conceptually and defined, stored attributes are more like member variables in other languages, except that:
- Can control read and write operations (
var
Can be read or written,let
Read only) - Property changes through the property monitor (
willSet
,didSet
) - Fast implementation of lazy loading (
lazy
Modified)
- Calculate attributeThe evaluated property does not store a value directly, but provides it
getter
To get a value, or to usesetter
To 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
- Computed properties do not store a value directly, but provide it
getter
To get a value, or to usesetter
To set other properties indirectly;
lazy
Properties must have initial values, they must be variables and not constants, because constants are determined before construction is completed;- 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;
- 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:
- Constructor method
- Default constructor method (overridden if there is a specified constructor method with arguments)
- Specify the constructor method
- Convenience constructor method
- Destructor method
- Object methods
- 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
- 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.
- All arguments to the constructor are both external and local by default
- Only convenience constructor methods can call the specified constructor of the current class
- The specified constructor method with arguments overrides the call to the default constructor method with no arguments
- 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
- A constructor of a parent class can only be called if the constructor is specified.
- 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.
- 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).
- A constant property can only be initialized in the constructor of the class that defines it, not in a subclass
- Before an object is released, it automatically calls its own destructor and then calls its parent’s destructor level by level.
- 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!