我正在寻找与Swift中的Java“.equals”完全相同的东西。
两个数据值val1
和val2
被声明为Any
(也尝试AnyObject
- 仍然没有运气)。如果数据是值类型或定义了isEqual
,则它们按值(==)进行比较,否则它们将作为参考进行比较(===)。
我希望==这样做,但它不会:编译器给出错误消息“二进制运算符==无法应用”。
有没有办法实现这个目标?
答案 0 :(得分:3)
我正在寻找完全相同的Java" .equals"在斯威夫特。
你正在寻找错误的语言。而且我也认为你从错误的角度看待平等检查。
Swift有Equatable
类型的概念来公开==
运算符,但该运算符仅适用于相同类型的具体值,Any
不符合条件此
Java中的情况有所不同,其中equals
几乎可以接收任何对象作为参数。这可能导致一些有趣的场景,例如使FileHandle
和House
相等,请不要试图说服我这实际上很有用,即使语言允许也是如此。
Swift的Equatable
vs Java' equals
具有巨大优势:它在编译时保证您不会尝试比较不兼容的类型。现在你可能会认为这在Java中比较严格,但这并不一定正确,因为在大多数情况下你不需要比较不同类型的值。
总而言之,如果您需要检查是否相等,请使用Equatable
。使您的类型符合此协议,并实现==
方法。让编译器完成剩下的工作。
答案 1 :(得分:0)
Swift是一种类型安全的语言。类型安全语言鼓励您清楚代码可以使用的值的类型。如果您的部分代码需要String,则不能错误地将其传递给Int。
您比较2任何值。我不能这样做,因为你无法比较String和Int值。您需要将两个值都转换为相同的类型然后进行比较
例如,您有2个值
let val1: Any (in fact this is String)
let val2: Any (in fact this is also String)
if let cast1 = val1 as? String,
let cast2 = val2 as? String {
return cast1 == cast2
}
答案 2 :(得分:0)
我对Java的经验不多,但根据您的描述,您可以定义一些函数重载来提供类似的功能
// Two instances of the same type which implements Equatable
func isEqual<T>(_ a: T, _ b: T) -> Bool where T : Equatable {
return a == b
}
// Pointer equal
func isEqual(_ a: AnyObject, _ b: AnyObject) -> Bool {
return a === b
}
// Between an object and an value or between 2 values that do not implement Equatable
func isEqual(_ a: Any, _ b: Any) -> Bool {
return false
}
// Test
assert(isEqual(1, 1) == true)
assert(isEqual("a", 1) == false)
assert(isEqual(NSData(), "a" as NSString) == false)
assert(isEqual("a", NSDecimalNumber(value: 42)) == false)
// Two instance values that do not implement Equatable
struct A { }
struct B { }
assert(isEqual(A(), B()) == false)
// Pointer equal
var num = 42
let ptr1 = withUnsafePointer(to: &num) { $0 }
let ptr2 = withUnsafePointer(to: &num) { $0 }
assert(isEqual(ptr1, ptr2) == true)
答案 3 :(得分:0)
Java中的equals
方法在所有对象上实现。但是,它的每个实现都应首先检查这两个对象是否具有相同的类:
boolean isEquals(Object otherObject) {
if (this == otherObjects) { return true } // check pointer equality
if (!(otherObject instanceOf MyObject) { return false }
MyObject o = (MyObject) otherObject;
// compare attributes of o and this to check if they are equal
}
这是一个非常通用的实现,它不是很强大。它可以让你比较不同类型的对象,例如String
和Integer
永远不会相等。这不是优势,这是一个弱点。
这就是为什么Java有多个更具体的重载,例如String.isEqualToString(String)
,只接受String
。
Swift强制执行类型安全,因此您永远无法比较两个随机对象。您始终必须比较相同类型的对象。
let string1 = "a"
let string2 = "b"
let int1 = 1
string1 == string2 // valid
string1 == int1 // does not make sense, cannot be compiled
你应该习惯它,因为它使你的代码类型安全,并且它将捕获错误。
您遇到的问题可能是因为您甚至使用Any
或AnyObject
等类型。尽可能不要使用这种类型 - 这几乎总是如此。相反,让你的类通用。
仅仅为了完整性,让我们看看如何在Swift中实现类似的概念:
// this is the interface
protocol JavaEquality {
func javaEquals(other: Any) -> Bool
}
// two structs/objects are equal only if their references are equal
extension JavaEquality {
func javaEquals(other: Any) -> Bool {
guard
let selfObject = self as? AnyObject,
let otherObject = other as? AnyObject
else {
return false
}
if selfObject === otherObject {
return true
}
return false
}
}
// implement for equatable structs/objects
extension JavaEquality where Self: Equatable {
func javaEquals(other: Any) -> Bool {
guard type(of: self) == type(of: other) else {
return false
}
return self == (other as! Self)
}
}
// let's test this
class A: Equatable {
let x: Int
init(x: Int) {
self.x = x
}
static func == (left: A, right: A) -> Bool {
return left.x == right.x
}
}
class B: A {}
// the only flaw is that you have to add the protocol to any struct/object you need
extension String: JavaEquality {}
extension Int: JavaEquality {}
extension NSNumber: JavaEquality {}
extension A: JavaEquality {}
let string1 = "a"
let string2 = "a"
let string3 = "b"
let int1 = 1
let number1 = A(x: 100)
let number2 = A(x: 100)
let number3 = A(x: 200)
let number4: B = B(x: 100)
let number5: A = B(x: 100)
print(string1.javaEquals(other: string2)) // true
print(string1.javaEquals(other: string3)) // false
print(string1.javaEquals(other: int1)) // false
print(number1.javaEquals(other: number2)) // true
print(number1.javaEquals(other: number3)) // false
print(number1.javaEquals(other: number4)) // false
print(number4.javaEquals(other: number5)) // true