【问题标题】:Swift "is" operator with type stored in variableSwift“is”运算符,类型存储在变量中
【发布时间】:2025-12-01 20:45:02
【问题描述】:

这段代码按预期工作。 "integer is int" 打印在输出中。

let integer = Int()

if integer is Int {
    println("integer is int")
}
else {
    println("integer is not int")
}

我想以与使用 isKindOfClass 方法相同的方式使用 is 运算符 - 将类(或更确切地说是类型)存储在变量中。它看起来像这样:

let integer = Int()
let intType : Any = Int.self

if integer is intType {
    println("Integer is int")
}
else {
    println("Integer is not int")
}

不幸的是,这会产生错误:Use of undeclared type 'IntType'

IntTypeif 条件下的颜色(如果将其粘贴到操场上)甚至与源代码中的其他位置不同,这表明(如错误消息所述)它被视为类名(如IntType 将是一个类)。但事实并非如此。意思是is运算符不能和右边的变量一起使用?

我想使用is 运算符,因为它不仅可以比较类,还可以比较其他类型。

如何检查 value 是否具有我期望的类型?


我找到了肮脏的解决方案,但它真的很不可靠......

let integer = Int()
let intType : Any = Int.self

func ==(left: Any, right: Any) -> Bool {
    let leftString = "\(left)"
    let rightString = "\(right)"
    return leftString == rightString
}

if (integer.dynamicType as Any) == intType {
    println("true")
}
else {
    println("false")
}

工作完美,但要小心 - 因为这也是正确的:

if (integer.dynamicType as Any) == ("Swift.Int" as Any) {
    println("true")
}
else {
    println("false")
}

有没有更好的办法?


好的,我将进一步解释我想要实现的目标。我有管理通用类实例实例的对象。在某些时候,我需要根据泛型类型选择其中一个泛型类实例。示例:

class GenericClass<T> {}

struct ToolInfo {
    let tool : AnyObject
    let jobType : Any
}

class Manager {
    var tools = Array<ToolInfo>()

    func pickToolForTheJob(job : Any) -> AnyObject {
        return tools.magicMethodWhichReturnProperTool()
    }
}

let viewTool = GenericClass<UIView>()
let rectangleTool = GenericClass<CGRect>()

let manager = Manager()
manager.tools.append(ToolInfo(tool: viewTool, jobType: UIView.self))
manager.tools.append(ToolInfo(tool: rectangleTool, jobType: CGRect.self))

manager.pickToolForTheJob(UIView()) // i want to get viewTool here
manager.pickToolForTheJob(CGRect()) // i want to get rectangleTool here

目前我有ToolInfo 结构,因为据我所知,在实例化泛型类对象时不可能在&lt;&gt; 中传递类型。但我还是无法比较。

【问题讨论】:

  • 也想过实现 === 操作符,但并没有优雅地解决它。另一种想法是将其包装在 struct 中,就像可选的那样,但不知道它是否适合您。
  • 不确定为什么需要将类存储到变量中,但我认为 typealias 是为这些东西制作的
  • 伙计们,我已经更新了问题以显示我的问题,也许你们中的一些人会建议其他方法来解决这个问题。 @rshev 它会是什么样子?您能否进一步解释(使用结构)或显示一些伪代码示例?
  • @zellb 使用 typealias 会是什么样子?
  • typealias intType = Int

标签: swift types


【解决方案1】:

这是我对enum 类型容器的实验(对不起,在前面的评论中错误地写成了struct):

enum TypeContainer {
    case SomeInt(Int)
    case SomeString(String)
    case SomeBool(Bool)

    init(int: Int) {
        self = .SomeInt(int)
    }

    init(string: String) {
        self = .SomeString(string)
    }

    init(bool: Bool) {
        self = .SomeBool(bool)
    }
}

let a = TypeContainer(string: "123")
let b = TypeContainer(int: 88)
let c = TypeContainer(bool: true)

switch a {
case .SomeInt(let i):
    println(i)
case .SomeString(let s):
    println(s)
case .SomeBool(let b):
    println(b)
default:
    break
}

你可以在你的项目中做这样的事情。

【讨论】:

    【解决方案2】:

    表示is运算符不能和右边的变量一起使用?

    正确。 is 的右侧必须在编译时进行硬编码。

    如果您不需要多态性并且您的类型是类类型,则可以使用=== 将实例的dynamicType 与类类型进行比较。这是在纯 Swift 中获得类型变量右侧的唯一方法。

    【讨论】:

    • 你说“你的类型是类类型”。这意味着不可能检查非类类型的比较类型?如果您可以使用此信息更新您的答案以使其清晰可见,我会接受此答案作为结束此问题。
    • "这意味着无法检查非类类型的比较类型?"您可以将它们与is 进行比较。但如果右侧是某种类型的变量,则不是。正如我在回答中所说,is 的右侧必须是硬编码的。这是因为 Swift 对打字很严格。它需要知道在编译时的所有东西的类型。
    • 我不知道“这个”是什么。
    最近更新 更多