Как сравнить "любые" типы значений
У меня есть несколько типов значений "Any", которые я хочу сравнить.
var any1: Any = 1
var any2: Any = 1
var any3: Any = "test"
var any4: Any = "test"
print(any1 == any2)
print(any2 == any3)
print(any3 == any4)
Использование оператора == показывает ошибку:
"Двоичный оператор" == "не может применяться к двум" Любые "(aka 'protocol < > ')"
Каким образом это можно сделать?
Ответы
Ответ 1
Единственный способ сделать это - это функция, ==
от ==
которая принимает параметр типа, а затем сравнивает значения, если они оба относятся к этому типу:
func isEqual<T: Equatable>(type: T.Type, a: Any, b: Any) -> Bool {
guard let a = a as? T, let b = b as? T else { return false }
return a == b
}
Теперь, используя ваши переменные выше, вы можете сравнить их следующим образом:
var any1: Any = 1
var any2: Any = 1
var any3: Any = "test"
var any4: Any = "test"
isEqual(Int.self, a: any1, b: any2) // true
isEqual(Int.self, a: any2, b: any3) // false
isEqual(String.self, a: any3, b: any4) // true
Ответ 2
Чтобы использовать оператор ==
, тип должен соответствовать протоколу Equatable
. Протокол Any
не соответствует протоколу Equatable
, поэтому нет возможности сравнить два значения Any
. Это логично - Any
является слишком широким термином - значения не могут иметь "общего знаменателя".
Что еще, Swift не позволяет сравнивать два значения Equatable
, которые имеют другой тип. Например. оба Int
и String
соответствуют Equatable
, но 1 == "1"
не компилируется. Причиной этого является объявление протокола ==
in Equatable
: func ==(lhs: Self, rhs: Self) -> Bool
. Это "Я" в основном означает, что оба аргумента должны иметь один и тот же тип. Это он вроде заполнителя - в реализации для определенного типа, Self
следует заменить на имя этого типа.
Ответ 3
Мы можем решить это следующим образом
enum SwiftDataType
{
case String
case Int
case Int64
case Double
case Bool
case Undefined
}
func getType( of : Any ) -> SwiftDataType
{
if let type = of as? String
{
return SwiftDataType.String
}
else if let type = of as? Int
{
return SwiftDataType.Int
}
else if let type = of as? Int64
{
return SwiftDataType.Int64
}
else if let type = of as? Double
{
return SwiftDataType.Double
}
else if let type = of as? Bool
{
return SwiftDataType.Bool
}
else
{
return SwiftDataType.Undefined
}
}
func isEqual( a : Any, b : Any ) -> Bool
{
let aType : SwiftDataType = getType( of : a )
let bType : SwiftDataType = getType( of : b )
if aType != bType
{
print("Type is not Equal -> \(aType)")
return false
}
else
{
switch aType {
case SwiftDataType.String :
guard let aValue = type as? String, let bValue = rtype as? String else
{
return false
}
return aValue == bValue
case SwiftDataType.Int :
guard let aValue = type as? Int, let bValue = rtype as? Int else
{
return false
}
return aValue == bValue
case SwiftDataType.Int64 :
guard let aValue = type as? Int64, let bValue = rtype as? Int64 else
{
return false
}
return aValue == bValue
case SwiftDataType.Double :
guard let aValue = type as? Double, let bValue = rtype as? Double else
{
return false
}
return aValue == bValue
case SwiftDataType.Bool :
guard let aValue = type as? Bool, let bValue = rtype as? Bool else
{
return false
}
return aValue == bValue
default:
return false
}
}
}