Swift中元词类型.Type
和.self
之间有什么区别?
.self
和.Type
是否会返回struct
?
我了解.self
可用于检查dynamicType
。你如何使用.Type
?
答案 0 :(得分:31)
这是一个简单的例子:
func printType<T>(of type: T.Type) {
// or you could do "\(T.self)" directly and
// replace `type` parameter with an underscore
print("\(type)")
}
printType(of: Int.self) // this should print Swift.Int
func printInstanceDescription<T>(of instance: T) {
print("\(instance)")
}
printInstanceDescription(of: 42) // this should print 42
假设每个实体由两件事代表:
输入:# entitiy name #
元节类型:# entity name # .Type
元类型类型是指任何类型的类型,包括类类型,结构类型,枚举类型和协议类型。
您可以快速注意到这是递归的,可以使用(((T.Type).Type).Type)
等类型。
.Type
返回元类型的实例。
我们有两种方法可以获得元类型的实例:
在.self
这样的具体类型上调用Int.self
,这将创建一个
静态元类型实例Int.Type
。
从任何实例中获取动态元类型实例
type(of: someInstance)
。
危险区域:
struct S {}
protocol P {}
print("\(type(of: S.self))") // S.Type
print("\(type(of: S.Type.self))") // S.Type.Type
print("\(type(of: P.self))") // P.Protocol
print("\(type(of: P.Type.self))") // P.Type.Protocol
.Protocol
是另一种元型,只存在于协议的上下文中。也就是说,我们无法表达我们只想要P.Type
。这可以防止所有通用算法与协议元类型一起使用,并可能导致运行时崩溃。
对于更多好奇的人:
type(of:)
函数实际上是由编译器处理的,因为.Protocol
创建了不一致。
// This implementation is never used, since calls to `Swift.type(of:)` are
// resolved as a special case by the type checker.
public func type<T, Metatype>(of value: T) -> Metatype { ... }
答案 1 :(得分:21)
在哪里使用?
如果您正在编写/创建一个接受类型的函数,例如UIView.Type
,不一个实例,例如UIView()
然后你会写T.Type
作为参数的类型。它作为参数的期望可以是:String.self
,CustomTableView.self
,someOtherClass.self
。
通常需要一个类型的函数,是一个实例化对象的函数。我可以想到两个很好的例子:
tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: "CustomTableViewCell")
请注意,您已通过CustomTableViewCell.self
。如果稍后您尝试将CustomTableViewCell
类型的tableView出列但未注册CustomTableViewCell
类型,那么它将崩溃,因为tableView没有出列/实例化任何tableviewcells {{1 }类型。
CustomTableViewCell
注意struct GroceryProduct: Codable {
var name: String
var points: Int
var description: String?
}
let json = """
{
"name": "Durian",
"points": 600,
"description": "A fruit with a distinctive scent."
}
""".data(using: .utf8)!
let decoder = JSONDecoder()
let product = try decoder.decode(GroceryProduct.self, from: json)
print(product.name)
。因为您传递了try decoder.decode(GroceryProduct.self, from: json)
,所以它知道它需要实例化GroceryProduct.self
类型的对象。如果它不能那么就会抛出错误
有关内部及其工作原理的更多信息:
类,结构或枚举类型的元类型是其名称 该类型后跟.Type。协议类型的元类型 - 不是 在运行时符合协议的具体类型是名称 该协议后跟.Protocol。例如,元的类型 类类型
GroceryProduct
是SomeClass
,其元类型为。{1}} 协议SomeClass.Type
为SomeProtocol
。来自Apple:metaType Type
Under the hood SomeProtocol.Protocol
AnyClass
基本上,您会看到typealias AnyClass = AnyObject.Type // which is why you see T.Type
,AnyClass
,Any.Type
,因为它需要某种类型。我们看到的一个非常常见的地方是,当我们想要使用AnyObject.Type
func 为我们的tableView注册类时。
register
如果您对Swift的内容感到困惑。&#39;然后执行上面的操作,然后查看here
中的评论上述内容也可以写成:
func register(_ cellClass: Swift.AnyClass?, forCellReuseIdentifier identifier: String)
您可以使用 postfix 自我表达式将类型作为值进行访问。 例如,SomeClass.self返回SomeClass本身,不一个实例 SomeClass。 SomeProtocol.self返回SomeProtocol本身,不 在运行时符合SomeProtocol的类型的实例。您 可以使用类型(of :)表达式来访问类型的实例 该实例的动态,运行时类型为值,如下所示 示例显示:
来自Apple:metaType Type
游乐场代码:
简单示例
func register(_ cellClass: AnyObject.Type, forCellReuseIdentifier identifier: String)
硬例
struct Something {
var x = 5
}
let a = Something()
type(of:a) == Something.self // true
我强烈建议您阅读 Apple documentation on Types。另请参阅here
答案 2 :(得分:13)
它们在语法上出现在不同的地方。
在语法上你必须指定类型的位置,Something.Type
是一个有效类型,对应于Something
的元类型(类的元类)类型。 Something.self
不是类型的有效语法。
在语法上你必须编写表达式的地方,Something.self
是一个有效的表达式。它是Something.Type
类型的表达式,值是表示类型Something
的事物(&#34;类对象&#34;在类的情况下)。 Something.Type
不是有效的表达式语法。
答案 3 :(得分:2)
这是今天让我感到困惑的那些话题之一。
我正在编写一个通用函数:
func foo<T: Protocol>(ofType: T.Type) {
T.bar()
}
并尝试按以下方式调用它:
foo(ofType: ClassImplementingProtocol.Type) // Compiler error
花了大约30分钟研究它为什么不起作用。然后我尝试了这个:
foo(ofType: ClassImplementingProtocol.self) // Works
结果发现Xcode的代码完成非常不好表现出元数据类型和类型之间的区别...从代码完成弹出窗口中,.self和.Type看起来是一样的东西:
但是它的“类似于im 5的解释”是,当您具有Class.Type的方法参数时,它期望的是Class.Type的实例。
Class.self返回Class.Type的实例,而Class.Type则引用Class.Type ...
很不清楚你是否问我。
答案 4 :(得分:0)
元类型.Type
Metatype
是一种类型,它允许您访问类和结构的部分[About] 类型(不是实例),如初始化器class 和 static[About] 属性和方法
let var1: String = HelloWorld
let var2: String.Type = HelloWorld.self
一些实验:
class SomeClass {
required init() { }
class func foo1() { }
static func foo2() { }
func foo3() { }
}
class SomeSubClass: SomeClass { }
let a1: SomeClass = SomeClass()
let a2: SomeClass = a1
let a3: SomeClass = a1.self
SomeClass.self.foo1() //class func
SomeClass.foo1() //class func
//static. metatype by type(class name) <class_name/structure_name>.self
let c1: SomeClass.Type = SomeClass.self
//dynamic. metatype by instance
let c2: SomeClass.Type = type(of: a1)
//access to type's init, class, static throught Metatype
let d1: SomeClass = c1.self.init()
let d2: SomeClass = c1.init()
//call
c1.foo1() //class func
c1.foo2() //static func
// c1.foo3() //instance func. Instance member 'foo3' cannot be used on type 'SomeClass'
// c1.foo3(SomeClass()) //Expression resolves to an unused function
//Sub
// <class_name>.Type allows to save class and sunclass
var e1: SomeClass.Type = SomeClass.self //class
e1 = SomeSubClass.self //sub class
//Any.Type allows to save class and struct
var e2: Any.Type = SomeClass.self //class
e2 = String.self //struct
//AnyObject.Type allows to save only class
var e3: AnyObject.Type = SomeClass.self //class
e3 = NSString.self //class
获取字符串
let typeString = "\(SomeType.Type)"
func register<T>(instance: T) {
instanceString = String(describing: type(of: instance))
}