Programing

==와 ===의 차이점

lottogame 2020. 3. 21. 10:11
반응형

==와 ===의 차이점


신속하게 두 개의 항등 연산자가있는 것 같습니다 : double equals ( ==) 및 triple equals ( ===), 둘 사이의 차이점은 무엇입니까?


한마디로 :

== 연산자는 인스턴스 값이 같은지 확인합니다. "equal to"

=== 연산자는 참조가 동일한 인스턴스를 가리키는 지 확인합니다. "identical to"

긴 답변 :

클래스는 참조 유형이며, 여러 상수 및 변수가 배후에서 클래스의 동일한 단일 인스턴스를 참조 할 수 있습니다. 클래스 참조는 런타임 스택 (RTS)에 유지되고 해당 인스턴스는 메모리의 힙 영역에 유지됩니다. 동일성을 제어하면 ==인스턴스가 서로 같은지 여부를 의미합니다. 같은 인스턴스 일 필요는 없습니다. 이를 위해 사용자 정의 클래스에 평등 기준을 제공해야합니다. 기본적으로 사용자 정의 클래스 및 구조에는 "같음"연산자 ==및 "같지 않음 "연산자로 알려진 동등 연산자의 기본 구현이 수신 되지 않습니다 !=. 이를 위해서는 커스텀 클래스가 Equatable프로토콜 을 준수해야하며 static func == (lhs:, rhs:) -> Bool기능

예를 보자.

class Person : Equatable {
    let ssn: Int
    let name: String

    init(ssn: Int, name: String) {
        self.ssn = ssn
        self.name = name
    }

    static func == (lhs: Person, rhs: Person) -> Bool {
        return lhs.ssn == rhs.ssn
    }
}

P.S.: ssn (사회 보장 번호)은 고유 한 번호이므로 이름이 같은지 비교할 필요가 없습니다.

let person1 = Person(ssn: 5, name: "Bob")
let person2 = Person(ssn: 5, name: "Bob")

if person1 == person2 {
   print("the two instances are equal!")
}

person1 및 person2 참조는 힙 영역에서 서로 다른 두 인스턴스를 가리 키지 만 ssn 숫자가 같기 때문에 인스턴스가 동일합니다. 따라서 출력은the two instance are equal!

if person1 === person2 {
   //It does not enter here
} else {
   print("the two instances are not identical!")
}

===연산자는 참조가 동일한 인스턴스를 가리키는 지 확인합니다 "identical to". person1과 person2는 힙 영역에 서로 다른 두 개의 인스턴스가 있으므로 동일하지 않고 출력이 다릅니다.the two instance are not identical!

let person3 = person1

P.S: 클래스는 참조 유형이며 person1의 참조는이 할당 조작으로 person3에 복사되므로 두 참조 모두 힙 영역에서 동일한 인스턴스를 가리 킵니다.

if person3 === person1 {
   print("the two instances are identical!")
}

그들은 동일하며 출력은 the two instances are identical!


!=====신원 연산자이며, 두 물체가 동일한 부호를 가지고 있는지 확인하기 위해 사용된다.

Swift는 두 개의 ID 연산자 (=== 및! ==)도 제공하는데, 두 개의 객체 참조가 모두 동일한 객체 인스턴스를 참조하는지 여부를 테스트하는 데 사용합니다.

발췌 : Apple Inc.“Swift Programming Language.” iBooks. https://itun.es/us/jEUH0.l


두 오브젝티브 C 및 신속한에서, ==!=숫자 값 값 어떤지 연산자 시험 (예를 들어, NSInteger, NSUInteger, int, 및 목표-C에서 Int, UInt등 신속한에서). 개체 (NSObject의 /의 NSNumber 및 서브 오브젝티브 C 및 신속한 참조 유형) 내용 ==!=즉, 동일한 해시 값 - - 또는 각각 같은 동일한 것이 아니다 개체 / 참조 형식이 동일한 동일한 것이 있는지 테스트 .

let a = NSObject()
let b = NSObject()
let c = a
a == b // false
a == c // true

Swift의 항등 항등 연산자 ===!==참조 항등 검사-따라서 항등 항등 연산자 IMO 라고합니다 .

a === b // false
a === c // true

Swift의 사용자 정의 참조 유형 (Equatable을 준수하는 클래스를 서브 클래스 화하지 않음)은 연산자와 동일하게 자동으로 구현되지 않지만 ID 동등성 연산자는 여전히 적용됨을 지적 할 가치가 있습니다. 또한를 구현 ==하면 !=자동으로 구현됩니다.

class MyClass: Equatable {
  let myProperty: String

  init(s: String) {
    myProperty = s
  }
}

func ==(lhs: MyClass, rhs: MyClass) -> Bool {
  return lhs.myProperty == rhs.myProperty
}

let myClass1 = MyClass(s: "Hello")
let myClass2 = MyClass(s: "Hello")
myClass1 == myClass2 // true
myClass1 != myClass2 // false
myClass1 === myClass2 // false
myClass1 !== myClass2 // true

이러한 동등 연산자는 어느 언어의 구조와 같은 다른 유형에 대해서도 구현되지 않습니다. 그러나 Swift에서 사용자 지정 연산자를 만들 수 있습니다. 예를 들어 CGPoint가 동일한 지 확인하는 연산자를 만들 수 있습니다.

infix operator <==> { precedence 130 }
func <==> (lhs: CGPoint, rhs: CGPoint) -> Bool {
  return lhs.x == rhs.x && lhs.y == rhs.y
}

let point1 = CGPoint(x: 1.0, y: 1.0)
let point2 = CGPoint(x: 1.0, y: 1.0)
point1 <==> point2 // true

스위프트 3 이상

===(또는 !==)

  • 값이 동일한 지 확인 합니다 (둘 다 동일한 메모리 주소를 가리킴) .
  • 참조 유형 비교 .
  • ==Obj-C 에서처럼 (포인터 평등).

==(또는 !=)

  • 값이 같은지 확인합니다 .
  • 값 유형 비교 .
  • isEqual:Obj-C 동작 의 기본값과 같습니다 .

여기서는 세 가지 인스턴스를 비교합니다 (클래스는 참조 유형입니다).

class Person {}

let person = Person()
let person2 = person
let person3 = Person()

person === person2 // true
person === person3 // false

===단순한 포인터 산술을 넘어서는 스위프트에는 미묘한 점이 있습니다 . 오브젝티브 C에 어떤 두 개의 포인터 (즉 비교할 수 있었지만 NSObject *포함) ==이 유형은 컴파일시 훨씬 더 큰 역할을하기 때문에 더 이상 사실 스위프트에 없습니다.

놀이터는 당신에게 줄 것이다

1 === 2                    // false
1 === 1                    // true
let one = 1                // 1
1 === one                  // compile error: Type 'Int' does not conform to protocol 'AnyObject'
1 === (one as AnyObject)   // true (surprisingly (to me at least))

문자열을 사용하면 다음에 익숙해 져야합니다.

var st = "123"                                 // "123"
var ns = (st as NSString)                      // "123"
st == ns                                       // true, content equality
st === ns                                      // compile error
ns === (st as NSString)                        // false, new struct
ns === (st as AnyObject)                       // false, new struct
(st as NSString) === (st as NSString)          // false, new structs, bridging is not "free" (as in "lunch")
NSString(string:st) === NSString(string:st)    // false, new structs
var st1 = NSString(string:st)                  // "123"
var st2 = st1                                  // "123"
st1 === st2                                    // true
var st3 = (st as NSString)                     // "123"
st1 === st3                                    // false
(st as AnyObject) === (st as AnyObject)        // false

그러나 다음과 같이 재미를 가질 수도 있습니다.

var st4 = st             // "123"
st4 == st                // true
st4 += "5"               // "1235"
st4 == st                // false, not quite a reference, copy on write semantics

나는 당신이 훨씬 더 재미있는 경우를 생각할 수 있다고 확신합니다 :-)

Swift 3 업데이트 (Jakub Truhlář의 의견에서 제안한대로)

1===2                                    // Compiler error: binary operator '===' cannot be applied to two 'Int' operands
(1 as AnyObject) === (2 as AnyObject)    // false
let two = 2
(2 as AnyObject) === (two as AnyObject)  // false (rather unpleasant)
(2 as AnyObject) === (2 as AnyObject)    // false (this makes it clear that there are new objects being generated)

이것은 좀 더 일관성과 같습니다 Type 'Int' does not conform to protocol 'AnyObject'그러나 우리가 다음 수,

type(of:(1 as AnyObject))                // _SwiftTypePreservingNSNumber.Type

그러나 명백한 전환은 어떤 일이있을 수 있음을 분명히합니다. String 쪽에서는 NSString우리가 사용할 수있는 한 계속 사용할 수 있습니다 import Cocoa. 그럼 우리는

var st = "123"                                 // "123"
var ns = (st as NSString)                      // "123"
st == ns                                       // Compile error with Fixit: 'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?
st == ns as String                             // true, content equality
st === ns                                      // compile error: binary operator '===' cannot be applied to operands of type 'String' and 'NSString'
ns === (st as NSString)                        // false, new struct
ns === (st as AnyObject)                       // false, new struct
(st as NSString) === (st as NSString)          // false, new structs, bridging is not "free" (as in "lunch")
NSString(string:st) === NSString(string:st)    // false, new objects
var st1 = NSString(string:st)                  // "123"
var st2 = st1                                  // "123"
st1 === st2                                    // true
var st3 = (st as NSString)                     // "123"
st1 === st3                                    // false
(st as AnyObject) === (st as AnyObject)        // false

두 개의 String 클래스를 갖는 것은 여전히 ​​혼란 스럽지만 암시 적 변환을 삭제하면 조금 더 눈에 잘 띄게됩니다.


예를 들어 클래스의 두 인스턴스를 만드는 경우 myClass:

var inst1 = myClass()
var inst2 = myClass()

해당 인스턴스를 비교할 수 있습니다.

if inst1 === inst2

인용 :

두 객체 참조가 모두 동일한 객체 인스턴스를 참조하는지 테스트하는 데 사용합니다.

발췌 : Apple Inc.“Swift Programming Language.” iBooks. https://itun.es/sk/jEUH0.l


Swift에는 === simbol이 있는데 이는 두 객체가 동일한 참조 동일한 주소를 참조한다는 것을 의미합니다

class SomeClass {
var a: Int;

init(_ a: Int) {
    self.a = a
}

}

var someClass1 = SomeClass(4)
var someClass2 = SomeClass(4)
someClass1 === someClass2 // false
someClass2 = someClass1
someClass1 === someClass2 // true

Any객체 와 관련된 약간의 기여 .

나는 단위 테스트로 일하고 있었고 NotificationCenter, Any평등을 비교하고 싶은 매개 변수로 사용 했습니다.

그러나 Any평등 작업에는 사용할 수 없으므로 변경해야했습니다. 궁극적으로, 나는 다음과 같은 접근 방식에 정착하여 특정 상황에서 평등을 얻을 수 있었으며 여기에 간단한 예가 나와 있습니다.

func compareTwoAny(a: Any, b: Any) -> Bool {
    return ObjectIdentifier(a as AnyObject) == ObjectIdentifier(b as AnyObject)
}

이 함수는 ObjectIdentifier를 활용 하여 객체에 고유 한 주소를 제공하므로 테스트 할 수 있습니다.

ObjectIdentifier위의 링크에서 Apple 당 참고해야 할 항목 하나 :

Swift에서는 클래스 인스턴스와 메타 타입 만 고유 한 ID를 갖습니다. 구조체, 열거 형, 함수 또는 튜플에 대한 동일성 개념은 없습니다.


==두 변수가 같은지 확인하는 데 사용됩니다 2 == 2. 그러나 ===동등의 경우, 즉 클래스의 경우 동일한 객체 예제를 참조하는 두 인스턴스가 많은 경우 다른 많은 인스턴스가 보유하는 참조가 작성됩니다.


스위프트 4 : 단위 테스트사용한 또 다른 예 는 ===에서만 작동합니다.

참고 : 아래 테스트는 ==에서 실패하고 ===에서 작동합니다.

func test_inputTextFields_Delegate_is_ViewControllerUnderTest() {

        //instantiate viewControllerUnderTest from Main storyboard
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        viewControllerUnderTest = storyboard.instantiateViewController(withIdentifier: "StoryBoardIdentifier") as! ViewControllerUnderTest 
        let _ = viewControllerUnderTest.view

        XCTAssertTrue(viewControllerUnderTest.inputTextField.delegate === viewControllerUnderTest) 
    }

그리고 수업은

class ViewControllerUnderTest: UIViewController, UITextFieldDelegate {
    @IBOutlet weak var inputTextField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        inputTextField.delegate = self
    }
}

==를 사용하는 경우 단위 테스트의 오류는 Binary operator '==' cannot be applied to operands of type 'UITextFieldDelegate?' and 'ViewControllerUnderTest!'


  • 가치 평등

    • 목표 -C : isEqual:
    • 빠른: ==
  • 참조 평등

    • 목표 -C : ==
    • 빠른: ===

자세한 내용은 여기

참고 URL : https://stackoverflow.com/questions/24002819/difference-between-and

반응형