Java中“等于”等同于Swift

时间:2018-02-15 00:15:15

标签: swift

我正在寻找与Swift中的Java“.equals”完全相同的东西。

两个数据值val1val2被声明为Any(也尝试AnyObject - 仍然没有运气)。如果数据是值类型或定义了isEqual,则它们按值(==)进行比较,否则它们将作为参考进行比较(===)。

我希望==这样做,但它不会:编译器给出错误消息“二进制运算符==无法应用”。

有没有办法实现这个目标?

4 个答案:

答案 0 :(得分:3)

  

我正在寻找完全相同的Java" .equals"在斯威夫特。

你正在寻找错误的语言。而且我也认为你从错误的角度看待平等检查。

Swift有Equatable类型的概念来公开==运算符,但该运算符仅适用于相同类型的具体值,Any不符合条件此

Java中的情况有所不同,其中equals几乎可以接收任何对象作为参数。这可能导致一些有趣的场景,例如使FileHandleHouse相等,请不要试图说服我这实际上很有用,即使语言允许也是如此。

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
}

这是一个非常通用的实现,它不是很强大。它可以让你比较不同类型的对象,例如StringInteger永远不会相等。这不是优势,这是一个弱点。

这就是为什么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

你应该习惯它,因为它使你的代码类型安全,并且它将捕获错误。

您遇到的问题可能是因为您甚至使用AnyAnyObject等类型。尽可能不要使用这种类型 - 这几乎总是如此。相反,让你的类通用。

仅仅为了完整性,让我们看看如何在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