Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将非泛型ObjC类向上转换为Swift方法参数的父类_Swift_Objective C_Generics_Downcast_Upcasting - Fatal编程技术网

将非泛型ObjC类向上转换为Swift方法参数的父类

将非泛型ObjC类向上转换为Swift方法参数的父类,swift,objective-c,generics,downcast,upcasting,Swift,Objective C,Generics,Downcast,Upcasting,我在Objective-C中定义了一些类似的类: @interface Type: NSObject { } @end @interface SubType1: Type { } @end @interface SubType2: Type { } @end @interface Parent <T: __kindof Type *> : NSObject @property (nonatomic, strong) NSArray <T>

我在
Objective-C
中定义了一些类似的类:

@interface Type: NSObject {
    
}
@end

@interface SubType1: Type {
    
}
@end

@interface SubType2: Type {
    
}
@end

@interface Parent <T: __kindof Type *> : NSObject
@property (nonatomic, strong) NSArray <T> *anArray;
@property (nonatomic, strong) T anObject;
@end

@interface SubParent1: Parent<SubType1 *> {
    
}
@end

@interface SubParent2: Parent<SubType2 *> {
    
}
@end
我得到一个错误:
无法将“Parent”类型的值转换为预期的参数类型“Parent”

还尝试:

func callFunc<T>(parent: T) where T: Parent<Type>{

}
callFunc(parent: SubParent1())

编译器抱怨
sub1
sub2
表示“表达式类型在没有更多上下文的情况下是不明确的”。

这里的问题是您期望协方差,但Swift泛型通常不支持协方差

网络上有很多关于协方差的解释,所以我不在这里解释。但我将确切地说明协方差在您的示例类型中是多么不合理。考虑这个代码:

let sp1 = SubParent1()
let p = sp1 as Parent<Type>  // (1) Swift forbids this cast...
let t: Type = SubType2()
p.anObject = t               // (2) ...because this assigment would be unsound.


编辑:Rob Napier的回答正确地表明,您只需要在
T
上使用泛型,而不需要在
p
上使用泛型。这里的问题是您期望协方差,但Swift泛型通常不支持协方差

网络上有很多关于协方差的解释,所以我不在这里解释。但我将确切地说明协方差在您的示例类型中是多么不合理。考虑这个代码:

let sp1 = SubParent1()
let p = sp1 as Parent<Type>  // (1) Swift forbids this cast...
let t: Type = SubType2()
p.anObject = t               // (2) ...because this assigment would be unsound.


编辑:Rob Napier的回答正确地表明,您只需要在
T
上进行泛型,而不需要在
p
上进行参数化,而不是在
Parent
上进行参数化,而不是在
Type
上进行参数化。你的意思是:

func callFunc<T>(parent: Parent<T>) { ... }
func callFunc(父:父){…}

虽然您可以显式地调用
T:Type
,但这并不是必需的,因为Parent已经强制执行了。

您正在对
Parent
进行参数化,而不是
Type
,实际上您正在更改它。你的意思是:

func callFunc<T>(parent: Parent<T>) { ... }
func callFunc(父:父){…}

虽然您可以显式地调用
T:Type
,但这并不是真正必要的,因为父级已经强制执行了该操作。

只是一个观察-在Objective-C中,您将在最高、最抽象的级别上工作,它最终将实现最深入的调用,即使这破坏了系统。在Swift的安全环境中,您必须在尽可能最低、最具体的级别上工作,Swift将呼叫尽可能浅的人员以保持安全。感谢您提供的解决方案。你能帮我做“以后编辑”部分吗?编辑应该是一个新问题,但答案是在一般情况下是不可能的。仅使用编译时已知的信息,subParent()的精确返回类型是什么?在这种情况下,这甚至是不可能的,因为我可以通过任何类型的考试。我可以将
CBPeripheral
与程序中的
Type
一致,并且您必须返回一个
Parent
。你会怎么做?您可能需要的是协议或类型擦除器,但这取决于实际使用情况。您应该打开一个问题来解释调用代码的样子。@skaak我不太确定您在这里的意思。在ObjC和Swift中,传递特异性很高或很低的变量是很常见的。Swift往往比ObjC有更多的抽象代码。考虑编写代码,如非常抽象的协议,比如集合和Objc中所做的事情。如果我不举这个例子,很难继续讨论,但我的(具体的,不是一般的)结论是Swift迫使你尽可能具体地工作(保持安全?),即使这样,它也会在安全方面出错。哦,好吧,也许我会把这个例子作为一个问题发布出来,或者如果你真的想继续这一过程,也许我可以在聊天中向你展示它——仅仅是一个观察——在Objective-C中,你会在最高、最抽象的层次上工作,它最终会做出可能的最深刻的呼吁,即使这破坏了系统。在Swift的安全环境中,您必须在尽可能最低、最具体的级别上工作,Swift将呼叫尽可能浅的人员以保持安全。感谢您提供的解决方案。你能帮我做“以后编辑”部分吗?编辑应该是一个新问题,但答案是在一般情况下是不可能的。仅使用编译时已知的信息,subParent()的精确返回类型是什么?在这种情况下,这甚至是不可能的,因为我可以通过任何类型的考试。我可以将
CBPeripheral
与程序中的
Type
一致,并且您必须返回一个
Parent
。你会怎么做?您可能需要的是协议或类型擦除器,但这取决于实际使用情况。您应该打开一个问题来解释调用代码的样子。@skaak我不太确定您在这里的意思。在ObjC和Swift中,传递特异性很高或很低的变量是很常见的。Swift往往比ObjC有更多的抽象代码。考虑编写代码,如非常抽象的协议,比如集合和Objc中所做的事情。如果我不举这个例子,很难继续讨论,但我的(具体的,不是一般的)结论是Swift迫使你尽可能具体地工作(保持安全?),即使这样,它也会在安全方面出错。哦,好吧,也许我会把这个例子作为一个问题发布,或者如果你真的想继续下去,我可以在聊天中展示给你。谢谢你的解决方案。你能帮我处理“以后编辑”部分吗?谢谢你的解决方案。你能帮我做“以后编辑”部分吗?
func callFunc<T>(parent: Parent<T>) { ... }