Difference between self and self, = = and = = =

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

Keywords: iOS

Added by Webxplosion on Thu, 02 Sep 2021 23:16:46 +0300