1. self and self
1.1 self
As we all know, the self keyword refers to the current object in the instance method, which plays the same role as in OC, but it cannot be used in the class method in OC, but it can be used in swift. Next, let's take a look at the representation type of self in this environment.
- Type of self in the instance:
In the instance method, the type represented by self is SwiftTestClass_self type is the instance object of the current class
- self in type:
As shown in the figure above, the type of self is SwiftTestClass_self.Type type, then. What type is type? Literally, self is SwiftTestClass_self type itself
If we add a static constant to a class, we can access this constant in class methods and today's methods through self.xxx, because they all belong to the type itself. Self.xxx is also accessing the constant of the class itself
1.2 Self
1.2.1 Self in example method
Self can access static properties through Self.xxx in instance methods, static methods and class methods
static let classLet: Int = 0 ///Example method func instanceMethod() -> Void { print("Self.class====\(Self.classLet)") } ///Static method static func classMethod() -> Void { print("Self.class====\(Self.classLet)") } ///Class method class func classMethod2() -> Void { print("Self.class====\(Self.classLet)") }
Next, let's observe the print result of the following code:
static func classMethod() -> Void { print("Self.self====\(Self.self)") print("self====\(self)") print("SwiftTestClass_self.self====\(SwiftTestClass_self.self)") print(Self.self==self) print(SwiftTestClass_self.self == self) print(SwiftTestClass_self.self == Self.self) } /** Print results: Self.self====SwiftTestClass_self self====SwiftTestClass_self SwiftTestClass_self.self====SwiftTestClass_self true true true */
According to the official documents, the value of Self is equal to that obtained by type(of: self), that is, it refers to dynamic acquisition
Let's look at the following example code:
static let classLet: Int = 0 ///Can be assigned successfully let instaceLet = classLet var instaceVar = classLet //Let instancelet2 = self.classlet 𞓜 self.classlet if the attribute in the class is used to initialize the attribute in the instance, the above assignment is OK, but slef.xxx is not, and a compilation error will occur, because the current self is undefined and does not exist lazy var instanceVar2 = Self.classLet // If you assign a value to a lazy loaded attribute, you can use self.xxx, but you cannot use self.xxx. If you use a lazy loaded attribute, you should pay attention to distinguishing between self and self. Because the instance has completed initialization, self is valid at this time. In this case, self represents the current instance object and self represents the current class. If you use class properties, you should use class objects, not instance objects
1.2.2 Self in the agreement
Self is used to restrict related types in the Protocol (instance loading xib creates spatial instances)
protocol GYLoadNibProtocl { } // When this protocol is used by UIView or UIView subclasses, the loadFromNib method is implemented by default, and subsequent implementation classes can be rewritten. //Self not only refers to the type implementing the protocol itself, but also includes subclasses of this type //Where self: uiview: limits that the method loadFromNib is implemented by default after the subclasses of View and View comply with this protocol extension GYLoadNibProtocl where Self : UIView { //class cannot be defined in the protocol. Only static can be defined static func loadFromNib(_ nibname: String? = nil) -> Self {//Self (uppercase) current class object //Self (lowercase) current object let loadName = nibname == nil ? "\(self)" : nibname! return Bundle.main.loadNibNamed(loadName, owner: nil, options: nil)?.first as! Self } }
Self is used for the return value of the Class
protocol TestProtocol { func getSelf() -> Self } class TestSubClass: TestProtocol { var name = "ceshi" //As the return value of the class class func getInstance() -> Self { return TestSubClass() as! Self } func getInstance2() -> Self { return TestSubClass() as! Self } } //At this point, Self is the type that ultimately implements the protocol let sub = TestSubClass() print(sub) let sub2 = TestSubClass.getInstance() print("sub2.name=====\(sub2.name)")
2. The difference between = = and = = =
2.1 = = Application
- ==: is the method defined in the Equatable protocol, and its negative form! =, User defined comparison rules are supported. Comparison rules can be defined by developers
//For this protocol, you can click api to see the specific introduction public protocol Equatable { /// Returns a Boolean value indicating whether two values are equal. /// /// Equality is the inverse of inequality. For any values `a` and `b`, /// `a == b` implies that `a != b` is `false`. /// /// - Parameters: /// - lhs: A value to compare. /// - rhs: Another value to compare. static func == (lhs: Self, rhs: Self) -> Bool }
We can customize a class and follow this protocol to implement the comparison method:
//Define a student class and declare two properties class Student: NSObject { var name: String var age: Int init(name: String, age: Int) { self.name = name self.age = age } //Custom objects. If you want to compare whether two objects are equal, you need to implement the isEqual method to implement the comparison rules. You guess that the underlying layer of "= =" is to call the isEqual method, and the isEqual method may be related to the hash value /** /// Subclasses of `NSObject` can customize Equatable conformance by overriding /// `isEqual(_:)`. If two objects are equal, they must have the same hash /// value, so if you override `isEqual(_:)`, make sure you also override the `hash` property. NSObject If you want to customize the comparison, you need to override isEqual(:) method. If two objects are compared, they must have the same hash value, so you must override isEqual(:), And confirm that you also override the hash property */ override func isEqual(_ object: Any?) -> Bool { if object == nil { return false } //Is is equivalent to the isKindof method in OC to judge whether it is an instance of a class or subclass if object is Student { let obj = object as! Student return name==obj.name && age == obj.age } else { return false } } //After practice, if you don't implement this property, just override isEqual(:) This method can also compare two objects override var hash: Int { return self.hash } } let student = Student.init(name: "guo", age: 22) let student1 = Student.init(name: "guo", age: 22) //If a student does not inherit NSObject and does not comply with the Equatable protocol, you cannot use "= =" to compare two student objects. If NSObject is integrated, you can use "= =" to compare, print("Compare two numbers=======\(student==student1)") //Print result: true
What happens if the custom class does not integrate NSObject but follows Equatable
class Person: Equatable { //Need to override = = method static func == (lhs: Person, rhs: Person) -> Bool { return lhs.name==rhs.name && lhs.age==rhs.age } var name: String var age: Int init(name: String, age: Int) { self.name = name self.age = age } } let person = Student.init(name: "guo", age: 22) let person1 = Student.init(name: "guo", age: 22) print("Compare two numbers=======\(person==person1)") //Print result: true
If the Equatable protocol is directly followed, the protocol method static func = = (LHS: person, RHS: person) - > bool {} needs to be implemented. You can directly implement custom comparison rules in this method, and then mark two objects
2.2 application of = = =
- ===: pointers are compared, so only reference types can be compared. Negative form! = =, Developer defined rules are not supported