当前位置: 首页 > 面试题库 >

如何将类类型作为函数参数传递

穆正青
2023-03-14
问题内容

我有一个通用函数,该函数调用Web服务并将JSON响应序列化回一个对象。

class func invokeService<T>(service: String, withParams params: Dictionary<String, String>, returningClass: AnyClass, completionHandler handler: ((T) -> ())) {

            /* Construct the URL, call the service and parse the response */
}

我要完成的是等效于此Java代码

public <T> T invokeService(final String serviceURLSuffix, final Map<String, String> params,
                               final Class<T> classTypeToReturn) {
}
  • 我要完成的方法签名正确吗?
  • 更具体地说,AnyClass将参数类型指定为正确的做法是正确的吗?
  • 调用该方法时,我将其MyObject.self作为returningClass值传递,但是出现编译 错误“无法将表达式的类型’()’转换为’String’类型”

    CastDAO.invokeService(“test”, withParams: [“test” : “test”], returningClass: CityInfo.self) { cityInfo in //

    }

编辑:

object_getClass如Holex所述,我尝试使用,但现在得到了:

错误:“类型’CityInfo.Type’不符合协议’AnyObject’”

需要做什么才能符合协议?

class CityInfo : NSObject {

    var cityName: String?
    var regionCode: String?
    var regionName: String?
}

问题答案:

您用错误的方式进行处理:在Swift中,与Objective-
C不同,类具有特定的类型,甚至具有继承层次结构(也就是说,如果类B继承自A,那么B.Type也继承自A.Type):

class A {}
class B: A {}
class C {}

// B inherits from A
let object: A = B()

// B.Type also inherits from A.Type
let type: A.Type = B.self

// Error: 'C' is not a subtype of 'A'
let type2: A.Type = C.self

这就是为什么您不应该使用的原因AnyClass,除非您真的想允许 任何
类。在这种情况下,正确的类型将是T.Type,因为它表示returningClass参数和闭包的参数之间的链接。

实际上,使用它代替AnyClass允许编译器正确地推断方法调用中的类型:

class func invokeService<T>(service: String, withParams params: Dictionary<String, String>, returningClass: T.Type, completionHandler handler: ((T) -> ())) {
    // The compiler correctly infers that T is the class of the instances of returningClass
    handler(returningClass())
}

现在存在构造T要传递给的实例的问题handler:如果您现在尝试运行代码,则编译器将抱怨T无法使用构建()。正确地这样:T必须明确地约束它,要求它实现特定的初始化程序。

这可以通过以下协议来完成:

protocol Initable {
    init()
}

class CityInfo : NSObject, Initable {
    var cityName: String?
    var regionCode: String?
    var regionName: String?

    // Nothing to change here, CityInfo already implements init()
}

然后,您只需要更改invokeService<T>到的一般约束即可<T: Initable>

小费

如果遇到诸如“无法将表达式的类型’()’转换为’String’类型”之类的奇怪错误,将方法调用的每个参数移至其自己的变量通常很有用。它有助于缩小导致错误的代码范围,并揭示类型推断问题:

let service = "test"
let params = ["test" : "test"]
let returningClass = CityInfo.self

CastDAO.invokeService(service, withParams: params, returningClass: returningClass) { cityInfo in /*...*/

}

现在有两种可能性:错误移至变量之一(这意味着存在错误的部分),或者您收到诸如“无法将表达式的类型转换()为类型($T6) -> ($T6) -> $T5” 之类的神秘信息。

后一个错误的原因是编译器无法推断您编写的内容的类型。在这种情况下,问题在于T仅在闭包的参数中使用,并且您传递的闭包没有指示任何特定类型,因此编译器不知道要推断的类型。通过更改包含的类型,returningClass可以T为编译器提供一种确定通用参数的方法。



 类似资料:
  • 我有一个抽象基类,它有以下私有变量 我希望其他所有扩展基类的类都实现以下方法 我的问题是,除了Map之外,我不能为实现选择任何其他类型 如果我不能控制选项映射的类型,但我想让initOptions方法的实现类知道映射中的键是String类型,值可以是任何对象,那么处理这种情况的正确方法是什么。

  • 问题内容: 当我定义一个自定义类型时,基础类型的类型似乎对我是否可以按原样将其传递给函数还是需要对其进行转换有所不同。 问题是: 为什么和起作用,但不起作用? https://play.golang.org/p/buKNkrg5y- 在这里,当我运行此函数时,它会抱怨,尽管它是基础类型。但是当我打电话或他们成功运行时。 问题答案: 和 您的新类型是2种不同的不同类型。在预期的地方,您必须传递typ

  • 问题内容: 问题摘要: 我想将具有类型参数(例如)的类作为类型参数传递给泛型方法。 假设我有一个方法: 当然,此方法对于任何类型的类都可以正常使用。我可以这样调用该方法,例如: 问题: 我发现我不能这样做: 从句法上讲,这显然是无效的。但是,我不确定如何实现这样的目标。我当然可以通过,但是泛型类型的添加使其在语法上不再有效,并且我想不出解决方法。 唯一的直接解决方案是这样的事情(看起来很愚蠢):

  • 所以我试着做下面这样的事情 并且定义为 当尝试编译代码时,clang给出错误。我发现这是因为你不能从lambda推断出类型。 所以这实际上是正确的,因为我实际上希望的参数类型是从的参数推导出的类型。 所以我的问题是,有没有可能排除参数的推导,而只是使用的推导类型?

  • 我正在尝试通过:如果流文件; 在我的主()中,到一个名为“FIFO”的类的构造函数:FIFO(文件); 在FIFO(FIFO.h)的头文件中,我有: 在FIFO.cc,我有: 我一直喜欢(还有更多,我只是粘贴其中一个): 在文件包括从/usr/lib/gcc/x86_64-redhat linux/4.4.7/…/…/…/…/包含/c /4.4.7/bits/localefwd.h: 43,从/u

  • 问题内容: 我有3类调用,和。 在我的课程中,我想要一个这样的方法: 因此,例如,我想: 如何将类名作为参数,并基于该类名从类名创建适当的对象? 问题答案: 使用反射是可能的。这里是给定的className(作为字符串传递)。此类将在内存中搜索(应该已经加载)。 作为字符串传递时要实例化的类的名称应 完全限定