问题描述
我想从方法中返回符合 MyProtocol
的 UIViewController
,所以我使用方法签名:
func myMethod< T其中T:UIViewController,T:MyProtocol>() - > T {
首先我不明白:if myMethod
返回例如一个 MyViewController
必须签名,我必须强制转换它:
class MyViewController:UIViewController,MyProtocol
我不能简单地 return MyViewController()
但我需要像这样投射它:返回MyViewController()as! T
- 为什么这是必要的?
第二件事:我该如何在某处使用此方法?我不能简单地说
let x = myMethod()as? UIViewController
当我得到错误时
通用参数'T'无法推断
我该如何实现这样的事情?如果我将它转换为 MyViewController
,它可以工作,但我想避免这种情况。
编辑:例子
class MyViewController:UIViewController,MyProtocol {
}
协议MyProtocol {
}
func myMethod< T>() - > T其中T:UIViewController,T:MyProtocol {
返回MyViewController()as! T //为什么演员是必要的?
}
好的,我确实得到了一部分,但为什么要转换为 T
有必要吗? MyViewController
是 UIViewController
的子类,并且符合协议,所以不需要转换,对吧?
func myMethod< T其中T:UIViewController,T:MyProtocol>() - > T
这个声明说:存在一个名为 myMethod $ c的函数$ c>,这样
myMethod
返回一些特定的 T
,其中 T
是 UIViewController
和 MyProtocol
的子类型。这并不是说实际上 T
是什么类型,并且并不表示只有一个这样的 myMethod
。如果有许多类型都是 UIViewController
的子类并且符合 MyProtocol
,则可以有很多类型。这些类型中的每一个都创建了一个新版本的 myMethod
(对于断言 myMethod
而言真的是一个新解决方案,例如一个函数确实存在)。
这不同于:
func myMethod() - > UIViewController
表示:函数 myMethod
返回任何子类型 UIViewController
。
Swift没有办法表达任何类型是UIViewController的子类并且是MyProtocol的子类型。您只能讨论符合该标准的特定类型。 Swift无法以这种方式组合类和协议;这只是当前语言的限制,而不是一个深层次的设计问题。
$ b $ < 问题。有许多函数满足您的
myMethod
声明。每个 T
您都可以插入符合规则的候选人。所以当你说 myMethod()
时,编译器不知道你指的是哪一个特定的 T
。 (我打算扩大这个答案,以更少的类型理论提供它,更多的是你怎么用代码来做,但donnywals已经有了一个很好的版本。 )
*到您编辑的问题*
func myMethod< T>() - > T其中T:UIViewController,T:MyProtocol {
返回MyViewController()as! T //为什么演员是必要的?
}
T
是一个特定类型由调用者决定。它不是符合任何类型,而是符合某些具体,具体的类型。考虑一下你所说的情况:
让vc:SomeOtherViewController = myMethod()
在这种情况下, T
是 SomeOtherViewController
。 MyViewController
不是那种类型,所以你对作为!
转换的操作很危险。
I'd like to return a UIViewController
conforming to MyProtocol
from a method, so I'm using the method signature:
func myMethod<T where T : UIViewController, T : MyProtocol>() -> T {
First thing I don't understand: if myMethod
returns e.g. a MyViewController
which has to following signature, I have to force cast it:
class MyViewController: UIViewController, MyProtocol
I cannot simply return MyViewController()
but I need to cast it like this: return MyViewController() as! T
- why is this necessary?
And the second thing: how can I use this method somewhere? I cannot simply say
let x = myMethod() as? UIViewController
as I get the error
Generic parameter 'T' could not be inferred
How can I achieve something like this? If I cast it to MyViewController
it works, but I would like to avoid that of course.
EDIT: Example
class MyViewController : UIViewController, MyProtocol {
}
protocol MyProtocol {
}
func myMethod<T>() -> T where T : UIViewController, T : MyProtocol {
return MyViewController() as! T // why is the cast necessary?
}
ok, I do get one part, but why is the cast to T
necessary? MyViewController
is a subclass of UIViewController
and conforms to the protocol, so no cast should be necessary, right?
func myMethod<T where T : UIViewController, T : MyProtocol>() -> T
This declaration says: There exists a function called myMethod
, such that myMethod
returns some specific T
where T
is a subtype of UIViewController
and also MyProtocol
. This does not say what type T
actually is, and it does not say that there is only one such myMethod
. There can be many if there are many type that are both subclasses of UIViewController
and conform to MyProtocol
. Every one of those types creates a new version of myMethod
(really a new solution to the assertion myMethod
makes, that such a function does exist).
This is not the same thing as:
func myMethod() -> UIViewController
That says: The function myMethod
returns any subtype of UIViewController
.
There is no way in Swift to express "any type that is a subclass of UIViewController and is a subtype of MyProtocol." You can only discuss a specific type that meets that criterial. Swift can't combine classes and protocols this way; it's just a current limitation of the language, not a deep design issue.
The specific versus any is the issue. There are many functions that satisfy your myMethod
declaration. Every T
you can plug in that conforms to the rules would be a candidate. So when you say myMethod()
, the compiler doesn't know which specific T
you mean.
(I was going to expand this answer to provide it in less type-theory, more "how do you do it in code" terms, but donnywals already has an excellent version of that.)
* To your edited question *
func myMethod<T>() -> T where T : UIViewController, T : MyProtocol {
return MyViewController() as! T // why is the cast necessary?
}
T
is a specific type decided by the caller. It is not "any type that conforms" it is "some specific, concrete type that conforms." Consider the case that you called:
let vc: SomeOtherViewController = myMethod()
In this case, T
is SomeOtherViewController
. MyViewController
is not that type, so what you're doing with the as!
cast is dangerous.
这篇关于Swift中的泛型 - “通用参数'T'无法推断出来的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!