I recently have been working on a script in which the need arose to distinguish whether an object saved to a variable is a Cocoa class constant itself or an instance object of that class. One way to make this determination is to test if the object equals its own class, which will return true for a class object and false for an instance object of that class. For example:
use framework "Foundation"
use scripting additions
set classObject to current application's NSString
set instanceObject to current application's NSString's stringWithString:"foobar"
classObject = classObject's |class|() --> true
instanceObject = instanceObject's |class|() --> false
The following are different ways of performing the class identity test, varying from one another in (1) how the class constant is specified (“class name” vs “class expression” method); (2) what the class constant is assigned to (local variable vs property); (3) how the class constant is assigned to a property (at declaration vs in a subsequent set statement); and (4) how the equality testing is done (the equal sign operator = vs ASObjC’s isEqual: method). The unexpected result is shown last:
use framework "Foundation"
use scripting additions
set classConstant_1 to current application's NSString -- "class name" assignment method
set classConstant_2 to class "NSString" -- "class expression" assignment method
property classConstant_3 : missing value
set my classConstant_3 to current application's NSString
property classConstant_4 : missing value
set my classConstant_4 to class "NSString"
property classConstant_5 : class "NSString"
(classConstant_1's isEqual:(classConstant_1's |class|())) --> true
(classConstant_2's isEqual:(classConstant_2's |class|())) --> true
(classConstant_3's isEqual:(classConstant_3's |class|())) --> true
(classConstant_4's isEqual:(classConstant_4's |class|())) --> true
(classConstant_5's isEqual:(classConstant_5's |class|())) --> true
(classConstant_1 = (classConstant_1's |class|())) --> true
(classConstant_2 = (classConstant_2's |class|())) --> true
(classConstant_3 = (classConstant_3's |class|())) --> true
(classConstant_4 = (classConstant_4's |class|())) --> true
(classConstant_5 = (classConstant_5's |class|())) --> false !!!
The unexpected result occurs only when (A) the class constant is assigned using the “class expression”, not the “class name”, assignment method; (B) the class constant is assigned to a property, not a local variable; (C) the assignment takes place in the property’s declaration statement, not in a subsequent set statement; and (D) the equal sign operator = is used for equality testing, not ASObjC’s isEqual: method. Any help in understanding this puzzling behavior is much appreciated.
As an ancillary question, what is the difference under the hood between the equal sign operator = vs ASObjC’s isEqual: method for equality testing. My understanding is that Objective C’s double equal sign operator == tests for true identity, i.e., two pointers pointing to the same location in memory, whereas isEqual: seems to be implemented differently depending on the class in which it is used and at least in some cases tests for measures of equality but not necessarily true identity. But where does ASObjC’s equal sign operator = fit in, and how does it differ from ASObjC’s implementation of the isEqual: method?
Thank you.