如何在 return 类型的函数中引用遵循协议的 class?
How to reference a class that follows a protocol in return type of function?
我有一个名为 Social Service 的协议,声明如下:
protocol SocialService: class {
class func testFunc()
}
遵循协议的 class 可能如下所示:
class Twitter: SocialService {
class func testFunc() {
}
}
我想要一个 return 遵循此协议的 class 方法,因此调用它应该如下所示:
let socialService = socialServiceForServiceType(serviceType: String)
我不确定我需要将什么作为此函数的 return 值类型。例如,这个:
func socialServiceForServiceType(serviceType: String) -> SocialService.Type
这里没有报错,但是按上面的方式调用,报错:
Accessing members of protocol type value 'SocialService.Type' is
unimplemented
编辑:我不想要那种类型的实例,我想要那种类型的 class。所以我想要一个 Twitter class,这样我就可以从上面的 SocialService 协议中调用 class 方法。
简单使用
func socialServiceForServiceType(serviceType: String) -> SocialService
协议可以是 return 类型的函数。
使用工厂模式实现同样的效果。
class SocialFactory : NSObject
{
class func socialServiceForServiceType(serviceType: String) -> SocialService?
{
switch serviceType
{
case "Twitter":
return Twitter();
case "Facebook":
return Facebook()
default:
return nil;
}
}
}
如错误所述,此功能未实现。然而...
I don't want an instance of that type, I want a class of that type. So I want a Twitter class, so I can call the class methods from the SocialService protocol on it.
我不确定您认为避免这种情况会得到什么。请记住 classes 不需要有成员变量,没有它们本质上只是函数指针的集合——这似乎是您正在寻找的。
如果您实现的 Twitter class 没有属性并且符合协议,那么调用该协议的方法将动态分派到该实例的实现:
protocol SocialService: class {
func testFunc()
}
class Twitter: SocialService {
func testFunc() {
println("Testing Twitter!")
}
}
func socialServiceForServiceType(serviceType: String) -> SocialService {
return Twitter()
}
let service = socialServiceForServiceType("blah")
// prints "Testing Twitter!"
service.testFunc()
如果您担心的是要将成员变量放在 Twitter
class 中,但又不想为某些功能增加开销,那么这可能表明您想要分解此功能分为两个不同的 classes。或者,如果您想要一个单例实例(例如处理连接性),那么还有其他模式可以处理这个问题。
完全同意 Airspeed Velocity,但我想扩展他的观点之一:
I'm not sure what you think you're getting from avoiding instances like this. Bear in mind classes don’t need to have member variables, and without them are essentially just collection of function pointers – which is what you seem to be looking for.
我假设你正在尝试做这样的事情:
func socialServiceForServiceType(serviceType: String) -> SocialService.Type
...
let cls = socialServiceForServiceType("twitter")
let conn = cls.connect(user)
或类似的东西。你不需要 classes 来实现它。你可以 return 函数。
typealias Connect = User -> Connection
func connectorForServiceType(serviceType: String) -> Connect {
switch serviceType {
case "twitter": return Twitter.Connect
...
}
}
let connect = connectorForServiceType("twitter")
let conn = connect(user)
如果您有一整套要打包在一起的函数,只需使用结构即可。
struct ServiceHandlers {
let connect : User -> Connection
let ping : () -> Bool
let name: () -> String
}
func standardPinger(host: String) -> () -> Bool {
return { host in
// perform an ICMP ping and return Bool
}
}
func handlersForServiceType(serviceType: String) -> ServiceHandlers {
switch serviceType {
case "twitter":
return ServiceHandlers(connect: Twitter.connect,
ping: standardPinger("www.twitter.com"),
name: { "Twitter" })
...
}
}
let service = handlersForServiceType("twitter")
let conn = service.connect(user)
在某些方面,这与 class 方法重复,但是 (a) class 方法所需的功能未实现,并且 (b) 这更加灵活。你可以 return 任何你想要的函数集合;它们不必都是 class 方法。拥有默认行为更容易(当您使用继承时,这在 Swift 中很难)。扩展起来更容易,因为您不必扩展所有 classes(请参阅我对 standardPinger
的使用,这是我编写的一些函数 returns 另一个函数; 它不一定是 class 方法)。
摆脱 class/inheritance 思维,只传递函数可能是 Swift 的主要优势。有时结构比协议更好。
我有一个名为 Social Service 的协议,声明如下:
protocol SocialService: class {
class func testFunc()
}
遵循协议的 class 可能如下所示:
class Twitter: SocialService {
class func testFunc() {
}
}
我想要一个 return 遵循此协议的 class 方法,因此调用它应该如下所示:
let socialService = socialServiceForServiceType(serviceType: String)
我不确定我需要将什么作为此函数的 return 值类型。例如,这个:
func socialServiceForServiceType(serviceType: String) -> SocialService.Type
这里没有报错,但是按上面的方式调用,报错:
Accessing members of protocol type value 'SocialService.Type' is unimplemented
编辑:我不想要那种类型的实例,我想要那种类型的 class。所以我想要一个 Twitter class,这样我就可以从上面的 SocialService 协议中调用 class 方法。
简单使用
func socialServiceForServiceType(serviceType: String) -> SocialService
协议可以是 return 类型的函数。
使用工厂模式实现同样的效果。
class SocialFactory : NSObject
{
class func socialServiceForServiceType(serviceType: String) -> SocialService?
{
switch serviceType
{
case "Twitter":
return Twitter();
case "Facebook":
return Facebook()
default:
return nil;
}
}
}
如错误所述,此功能未实现。然而...
I don't want an instance of that type, I want a class of that type. So I want a Twitter class, so I can call the class methods from the SocialService protocol on it.
我不确定您认为避免这种情况会得到什么。请记住 classes 不需要有成员变量,没有它们本质上只是函数指针的集合——这似乎是您正在寻找的。
如果您实现的 Twitter class 没有属性并且符合协议,那么调用该协议的方法将动态分派到该实例的实现:
protocol SocialService: class {
func testFunc()
}
class Twitter: SocialService {
func testFunc() {
println("Testing Twitter!")
}
}
func socialServiceForServiceType(serviceType: String) -> SocialService {
return Twitter()
}
let service = socialServiceForServiceType("blah")
// prints "Testing Twitter!"
service.testFunc()
如果您担心的是要将成员变量放在 Twitter
class 中,但又不想为某些功能增加开销,那么这可能表明您想要分解此功能分为两个不同的 classes。或者,如果您想要一个单例实例(例如处理连接性),那么还有其他模式可以处理这个问题。
完全同意 Airspeed Velocity,但我想扩展他的观点之一:
I'm not sure what you think you're getting from avoiding instances like this. Bear in mind classes don’t need to have member variables, and without them are essentially just collection of function pointers – which is what you seem to be looking for.
我假设你正在尝试做这样的事情:
func socialServiceForServiceType(serviceType: String) -> SocialService.Type
...
let cls = socialServiceForServiceType("twitter")
let conn = cls.connect(user)
或类似的东西。你不需要 classes 来实现它。你可以 return 函数。
typealias Connect = User -> Connection
func connectorForServiceType(serviceType: String) -> Connect {
switch serviceType {
case "twitter": return Twitter.Connect
...
}
}
let connect = connectorForServiceType("twitter")
let conn = connect(user)
如果您有一整套要打包在一起的函数,只需使用结构即可。
struct ServiceHandlers {
let connect : User -> Connection
let ping : () -> Bool
let name: () -> String
}
func standardPinger(host: String) -> () -> Bool {
return { host in
// perform an ICMP ping and return Bool
}
}
func handlersForServiceType(serviceType: String) -> ServiceHandlers {
switch serviceType {
case "twitter":
return ServiceHandlers(connect: Twitter.connect,
ping: standardPinger("www.twitter.com"),
name: { "Twitter" })
...
}
}
let service = handlersForServiceType("twitter")
let conn = service.connect(user)
在某些方面,这与 class 方法重复,但是 (a) class 方法所需的功能未实现,并且 (b) 这更加灵活。你可以 return 任何你想要的函数集合;它们不必都是 class 方法。拥有默认行为更容易(当您使用继承时,这在 Swift 中很难)。扩展起来更容易,因为您不必扩展所有 classes(请参阅我对 standardPinger
的使用,这是我编写的一些函数 returns 另一个函数; 它不一定是 class 方法)。
摆脱 class/inheritance 思维,只传递函数可能是 Swift 的主要优势。有时结构比协议更好。