Christopher Graf
Christopher Graf

Reputation: 2219

Overload Equality Operator (==) to compare String and Int

I am experiencing with protocols and challenged myself to write a code snippet that overloads the == operator so that it returns true when I compare a random String with value "42" with a Int of value 42. Please don't question the usefulness by simply returning 42 on a String, the main point is getting the Equality Operator to run on the two different types.

Here is what I tried:

Version 1

import Foundation

protocol IntTransformable: Equatable {
    func toInt() -> Int
}

extension String: IntTransformable {
    func toInt() -> Int {
        return 42
    }
}

extension Int: IntTransformable {
    func toInt() -> Int {
        return self
    }
}

extension IntTransformable {
    static func == (lhs: Self, rhs: Self) -> Bool {
        return lhs.toInt() == rhs.toInt()
    }
}

// throws: Ambiguous reference to operator function '=='
if "42" == 42 {
    print("equal")
} else {
    print("unequal")
}

Version 2

import Foundation

protocol IntTransformable: Equatable {
    func toInt() -> Int
}

extension String: IntTransformable {
    func toInt() -> Int {
        return 42
    }
}

extension Int: IntTransformable {
    func toInt() -> Int {
        return self
    }
}

extension IntTransformable {
    // throws: Protocol 'IntTransformable' can only be used as a generic constraint because it has Self or associated type requirements
    static func == (lhs: IntTransformable, rhs: IntTransformable) -> Bool {
        return lhs.toInt() == rhs.toInt()
    }
}

// throws: Ambiguous reference to operator function '=='
if "42" == 42 {
    print("equal")
} else {
    print("unequal")
}

Upvotes: 0

Views: 119

Answers (3)

Mojtaba Hosseini
Mojtaba Hosseini

Reputation: 119168

You should use these two functions:

func ==(lhs: String, rhs: @autoclosure ()->Int) -> Bool {
    guard let stringIntValue = Int(lhs) else { return false }
    return stringIntValue == rhs()
}

func ==(lhs: Int, rhs: String) -> Bool {
    guard let stringIntValue = Int(rhs) else { return false }
    return lhs == stringIntValue
}

But if you really want to involve Protocols here, you should do this like:

extension IntTransformable {
    static func ==<T: IntTransformable>(lhs: Self, rhs: T) -> Bool {
        return lhs.toInt() == rhs.toInt()
    }
}

Usage:

print( 42 == "42" )
print( "42" == 42 )

Upvotes: 3

matt
matt

Reputation: 534925

You're way overthinking this. There is no reason to use protocols here, and you really can't do it because protocols are not really types. Just write your operator(s) at top level:

func == (lhs: Int, rhs: String) -> Bool {
    return lhs == Int(rhs)
}
func == (lhs: String, rhs: Int) -> Bool {
    return Int(lhs) == rhs
}

Testing:

print(5 == "5") // true

Upvotes: 1

Stefan Mayer
Stefan Mayer

Reputation: 5

create a string extension, like

public string ToInt(this int value) { // some conversion code

return ConvertedStringValue; }

or you can use a uint.TryParse(string value, out uint output) this statement will return true if conversion is successful.

Upvotes: -3

Related Questions