This question already has an answer here:
How does a set determine that two objects are equal in dart?
(1 answer)
Closed 1 year ago.
I just stuffed a bunch of MyClass inside a Set in Dart. MyClass does not implement Comparable, and does not have an == operator defined. It compiled fine.
For this Set to detect duplicates properly, do I have to implement Comparable interface, or just override the == operator?
All Dart classes derive from Object, which does provide operator == and hashCode. Object's default implementations check for object identity; an instance of your class will compare equal only to itself.
If you want two different instances to be able to compare equal, then you need to:
Implement operator == and hashCode in your custom class. Set's default implementation is a LinkedHashSet, which does not use Comparable. (There is a SplayTreeSet implementation that does use Comparable, however, but lookup and insertions would be O(log n) instead of O(1).)
Alternatively use the LinkedHashSet constructor or the HashSet constructor and pass appropriate callbacks for equality and hash code computations.
Related
The enumerateAttribute(_:in:options:using:) method of NSAttributedString appears to equate arbitrary instances of type Any. Of course, Any does not conform to Equatable, so that should not be possible.
Question: How does the method compare one instance of Any to another?
Context: In Swift, I am subclassing NSTextStorage, and have need to provide my own implementation of this method in Swift.
Observations:
NSAttributedString attributes come in key-value pairs, with the keys being instances of type NSAttributedString.Key and the values being instances of type Any?, with each pair being associated with one or more ranges of characters in the string. At least, that is how the data structure appears from the outside; the internal implementation is opaque.
The enumerateAttribute method walks through the entire range of an NSAttributedString, effectively identifying each different value corresponding to a specified key, and with the ranges over which that value applies.
The values corresponding to a given key could be of multiple different types.
NSAttributedString seemingly has no way of knowing what underlying types the Any values might be, and thus seemingly no way of type casting in order to make a comparison of two given Any values.
Yet, the method somehow is differentiating among ranges of the string based on differences in the Any values.
Interestingly, the method is able to differentiate between values even when the underlying type does not conform to Equatable. I take this to be a clue that the method may be using some sort of reflection to perform the comparison.
Even more interesting, the method goes so far as to differentiate between values when the underlying type does conform to Equatable and the difference between two values is a difference that the specific implementation of Equatable intentionally ignores. In other words, even if a == b returns true, if there is a difference in opaque properties of a and b that are ignored by ==, the method will treat the values as being different, not the same.
I assume the method bridges to an implementation in ObjC.
Is the answer: It cannot be done in Swift?
As you know, Cocoa is Objective-C, so these are Objective-C NSDictionary objects, not Swift Dictionary objects. So equality comparison between them uses Objective-C isEqual, not Swift ==. We are not bound by Swift strict typing, the Equatable protocol, or anything else from Swift.
To illustrate, here's a slow and stupid but effective implementation of style run detection:
let s = NSMutableAttributedString(
string: "howdy", attributes: [.foregroundColor:UIColor.red])
s.addAttributes([.foregroundColor:UIColor.blue],
range: NSRange(location: 2, length: 1))
var lastatt = s.attributes(at: 0, effectiveRange: nil)
for ix in 1..<5 {
let newatt = s.attributes(at:ix, effectiveRange:nil)
if !(newatt as NSDictionary).isEqual(to: lastatt) {
print("style run ended at \(ix)")
lastatt = newatt
}
}
That correctly prints:
style run ended at 2
style run ended at 3
So since it is always possible to compare the attributes at any index with the attributes at another, it is possible to implement attribute enumeration in Swift. (Whether that's a good idea is another question.)
In C++ I would just compare the memory addresses of both objects. How would I do something similar in MATLAB?
Worst Case would be to have a static variable that iterates in each constructor and every object gets the current value as ID. But is there a better solution?
Thank you in advance.
#Edit:
I'd like to extend this question by assuming I have some given/not changeable classes inheriting handle and overloading eq. If I want to compare two objects of this class can I somehow cast both instances to handle and use the implementation of eq of the super class?
To test that two handle objects a and b refer to the same instance, you only need to use a == b. This is the same as eq(a, b). This is the defined behaviour of == for handle objects. I.e., for handle objects, == tests for equality of instances, not equality of the values within the instances. This is different from value objects.
For this to work you need to be using handle objects (classdef myObject < handle) because it doesn't make sense to test instances of value objects.
N.B. if you also need to get some kind of instance identifier for a handle object, then you need to do something like you describe using a persistent variable. Here's an example. In that case I would make that a base class for all your objects, so you wouldn't have to copy the same code into each class. But that's unnecessary if all you want to do is test two instances.
This question already has answers here:
Cannot assign property in method of struct
(2 answers)
Closed 7 years ago.
I'm studying swift and I'm trying to understand the difference between classes and struct, which as I understand it, is in these two points:
1) Classes are reference types, Whereas structures are value types. That means That When you pass an instance of a structure to a function, return an instance from a function, or assign the value of a variable That Refers to a structure to another variable, the instance is copied. In other words, structures exhibit pass-by-value behavior. Swift strings, arrays, and dictionaries are all Implemented as structures.
By contrast, class instances are passed by reference-no copy is taken.
2) Classes can be subclassed to add behavior; structures can not.
why these two errors?
depends on the structure ?, because a class does not give me the same error.
The reason you're getting those errors is that by default, the properties of a value type (i.e. a struct) cannot be modified from within its instance methods (e.g. your newRad() and plusOne() methods).
I want to change the format of my data, from RDD(Label:String,(ID:String,Data:Array[Double])) to an RDD Object with the label, id and data as components.
But when I print my RDD consecutively twice, the references of objects change :
class Data_Object(private val id:String, private var vector:Vector) extends Serializable {
var label = ""
...
}
First print
(1,ms3.Data_Object#35062c11)
(2,ms3.Data_Object#25789aa9)
Second print
(2,ms3.Data_Object#6bf5d886)
(1,ms3.Data_Object#a4eb65)
I think that explains why the subtract method doesn't work. So can I use subtract with objects as values, or do I return to my classic model ?
Unless you specify otherwise, objects in Scala (and Java) are compared using reference equality (i.e. their memory address). They are also printed out according to this address, hence the Data_Object#6bf5d886 and so on.
Using reference equality means that two Data_Object instances with identical properties will NOT compare as equal unless they are exactly the same object. Also, their references will change from one run to the next.
Particularly in a distributed system like Spark, this is no good - we need to be able to tell whether two objects in two different JVMs are the same or not, according to their properties. Until this is fixed, RDD operations like subtract will not give the results you expect.
Fortunately, this is usually easy to fix in Scala/Spark - define your class as a case class. This automatically generates equals and hashcode and toString methods derived from all of the properties of the class. For example:
case class Data_Object(id:String, label:String, vector:Vector)
If you want to compare your objects according to only some of the properties, you'll have to define your own equals and hashcode methods, though. See Programming in Scala, for example.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why does fast enumeration not skip the NSNumbers when I specify NSStrings?
I noticed some unexpected behavior while using fast enumeration recently. In hindsight I was probably expecting fast enumeration to do more than it's intended for, so I'm looking for some clarification on how it's actually works.
Say I have a parent class Shape with 2 child classes, 3SidedShape and 4SidedShape. I have an array called myShapes, that contains objects from both the 3 and 4 sided classes.
If I wanted to search through the array myShapes, but I'm only concerned with 3 sides shapes what I was doing is:
for (3SidedShape *shape in myShapes)
My thought was that I would only be iterating over objects of class 3SidedShape, but that is not the case? I guess I'm casting all objects as 3SidedShape whether they like it or not. I'm evening returning the object after as a completely different class. Granted I'm not calling any methods that both classes don't have, but I didn't expect class siblings to just re-cast so easily without a hitch? Did I just get lucky here or can you really enumerate as any class you please regardless of relation? Can anyone explain what actually happens during enumeration?
The type specified in a for...in loop, aka fast enumeration, casts all the elements in the collection to the specified type. The reason why they are "re-cast so easily" is that casting does NOT turn one type of object into another (how would that work?). It's a hint to the compiler telling it to treat the object as if it were the other type, as if to say "don't worry, this object is of (insert type), so type check it as such." Sending the object a message it can't handle, but the type it was casted to can, will still crash the app. What you should do is this:
for (id shape in myShapes){
if ([shape isKindOfClass: [3SidedShape class]]){
//insert code here
}
}
That code assumes nothing of type, using introspection to only perform the code for objects who are of type 3SidedShape or a subclass of 3SidedShape. For exact checking (excluding subclasses) use isMemberOfClass:. Be wary of using isMemberOfClass: to test membership of a class in a class cluster (NSNumber), however, due to their more complex internal implementation.