[英]Type casting in Swift 3
I want to check whether a generic type conforms to a protocol. 我想检查泛型类型是否符合协议。 If it is, I need to cast the type itself and call a static method against it. 如果是这样,我需要转换类型本身,并针对它调用静态方法。
func log<T>(object: T) {
if let C = T as? Loggable { // this line doesn't compile
print("\(C.description(of: object))")
} else {
print("\(object)")
}
}
Anybody knows if it's doable? 有人知道这是否可行吗?
UPDATE 更新
I confused you with my first code snippet. 我把我的第一个代码片段弄糊涂了。 Hopefully, second makes more sense. 希望第二更有意义。 I've made some changes thanks to the @portella's answer, but it's still not enough. 感谢@portella的回答,我进行了一些更改,但还不够。
func decodeObject<T>() -> T? {
guard let object = objects.first else {
return nil
}
objects.removeFirst()
if object is NSNull {
return nil
}
if T.self is Coding.Type { // the condition is fixed, thanks to @Hiron
if let data = object as? Data {
return type(of: (T.self as! Coding)).from(data: data) as? T
} else {
return nil
}
}
return object as? T
}
Does this fit your needs: 这是否符合您的需求:
protocol Loggable {
func log()
static func staticLog()
}
func log<L: Loggable>(object: L) {
object.log()
L.staticLog()
}
You ensure that all the objects sent into the function conforms to the protocol Loggable
您确保发送到函数中的所有对象均符合Loggable
协议
For me, i don't like this, but hope the following solution can help (i strongly recommend the first one): 对我来说,我不喜欢这样,但希望以下解决方案能对您有所帮助(我强烈建议您使用第一个):
protocol Loggable {
func log()
static func staticLog()
}
func log<L>(object: L) {
guard let loggableObject = object as? Loggable else {
print("💩 Not a loggable object")
return
}
loggableObject.log()
type(of: loggableObject).staticLog()
}
final class NotLoggableClass {}
final class LoggableClass: Loggable {
func log() {
print("👏")
}
static func staticLog() {
print("😕")
}
}
log(object: NotLoggableClass())
log(object: LoggableClass())
The call log(object: NotLoggableClass())
will return: 💩 Not a loggable object
调用log(object: NotLoggableClass())
将返回: 💩 Not a loggable object
The call log(object: LoggableClass())
will return: 👏😕
通话log(object: LoggableClass())
将返回: 👏😕
EDIT: regarding the update, do you want to check the argument type or the argument type? 编辑:关于更新,您是否要检查参数类型或参数类型? You are not sending any argument into your function, which seems odd. 您没有在函数中发送任何参数,这似乎很奇怪。 I think you would like to validate it, not the return, i guess. 我想我想您想验证它,而不是回报。 Is this what you are trying to achieve: 这是您要实现的目标:
protocol Coding {
associatedtype T
static func decodeObject<T>(data: Data) -> T?
}
extension UIImage: Coding {
typealias T = UIImage
static func decodeObject<T>(data: Data) -> T? {
return UIImage(data: data) as? T
}
}
Regarding your solution, i don't understand the objects
or where that came from. 关于您的解决方案,我不了解这些objects
或它们的来源。 If you want the generic type to conform with the Coding
protocol
you can make that with a constraint in the function declaration. 如果希望泛型类型符合Coding
protocol
,则可以在函数声明中添加约束。
Example: 例:
protocol Coding {
associatedtype T
static func from(data: Data) -> T?
}
func decodeObject<T: Coding>(_ objects: [Data]) -> T? {
guard let object = objects.first else {
return nil
}
var objects = objects
objects.removeFirst()
return T.from(data: object) as? T
}
extension String: Coding {
static func from(data: Data) -> String? {
return String(data: data, encoding: .utf8)
}
}
Although, i don't understand the objects, this should be something to be done by the type itself, not by a common helper or something, which seems to me what you are trying. 尽管我不理解这些对象,但这应该由类型本身来完成,而不是由公共帮助者完成,或者在我看来这是您要尝试的事情。
Try to avoid dynamic cast and type with Swift 😉 尝试避免动态转换并使用Swift type键入
Hope that helps 🍻 希望有帮助helps
Maybe you should write 也许你应该写
if T.self is Coding.Type
instead of 代替
if T.self is Coding
Let's say you have a protocol with a static method and a class which implements it: 假设您有一个带有静态方法的协议和一个实现该协议的类:
protocol Something {
static func doSomething()
}
class SomethingConcrete: Something {
static func doSomething() {
// does something concrete
}
}
Also there's a generic function. 还有一个通用功能。 If it gets the type Something
it calls it's static method (there's no object involved). 如果它得到某类型的Something
它将调用它的静态方法(不涉及任何对象)。
There's two ways of doing this: overloading and casting. 有两种方法:重载和强制转换。
Overloading (a credit to @portella) 超载 (归功于@portella)
func someFunction<T: Something>() {
T.doSomething()
}
func someFunction<T>() {
// does something else
}
Casting (uses a type check mentioned by @Hiron) 强制转换 (使用@Hiron提到的类型检查)
func someFunction<T>() {
if T.self is Something.Type {
(T.self as! Something.Type).doSomething()
} else {
// does something else
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.