如何在函数的返回类型中引用遵循协议的类?

时间:2015-04-02 10:53:45

标签: ios class swift protocols

我有一个名为Social Service的协议,声明如下:

protocol SocialService: class {
    class func testFunc()
}

遵循协议的类可能如下所示:

class Twitter: SocialService {
    class func testFunc() {

    }
}

我想要一个返回遵循此协议的类的方法,因此调用它将如下所示:

let socialService = socialServiceForServiceType(serviceType: String)

我不确定我需要把它作为此函数的返回值类型。例如,这个:

func socialServiceForServiceType(serviceType: String) -> SocialService.Type

这里没有给出错误,但尝试按上述方式调用它会产生错误:

  

访问协议类型值'SocialService.Type'的成员是   未实现

编辑:我不想要那种类型的实例,我想要一个这种类型的类。所以我想要一个Twitter类,所以我可以通过社交服务协议调用类方法。

4 个答案:

答案 0 :(得分:3)

如错误所述,此功能未实现。然而...

  

我不想要那种类型的实例,我想要一个这种类型的类。所以我想要一个Twitter类,所以我可以通过社交服务协议调用类方法。

我不确定你认为你从避免像这样的事件中获得了什么。请记住,类不需要有成员变量,没有它们本质上只是函数指针的集合 - 这就是你似乎在寻找的东西。

如果您实现的Twitter类没有属性且符合协议,那么调用该协议上的方法将动态调度到该实例的实现:

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类中,但是不希望某些特性的开销,那么这可能意味着你想要将这个功能分解为两个不同的类。或者,如果你想要一个单例实例(例如处理连接),那么还有其他模式来处理这个问题。

答案 1 :(得分:1)

简单地使用

func socialServiceForServiceType(serviceType: String) -> SocialService

协议可以是函数的返回类型。

答案 2 :(得分:1)

完全赞同Airspeed Velocity,但我想扩展他的一点:

  

我不确定你认为你从避免这样的事件中获得了什么。请记住,类不需要有成员变量,没有它们本质上只是函数指针的集合 - 这就是你似乎在寻找的东西。

我假设你正在尝试这样做:

func socialServiceForServiceType(serviceType: String) -> SocialService.Type
...
let cls = socialServiceForServiceType("twitter")
let conn = cls.connect(user)

或类似的东西。你不需要类来实现它。你可以返回功能。

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)

在某些方面,这与类方法重复,但(a)类方法所需的功能未实现,(b)这更灵活。您可以返回任何您想要的函数集合;他们并不一定都是阶级方法。拥有默认行为(使用继承时Swift很难)会更容易。它更容易扩展,因为你不一定要扩展所有类(参见我对standardPinger的使用,这是我编写的一些返回另一个函数的函数;它不必是一个类法)。

摆脱类/继承思维,只是传递函数可以成为Swift的一大优势。有时结构比协议更好。

答案 3 :(得分:0)

使用工厂模式实现相同目标。

class SocialFactory : NSObject
{
  class func socialServiceForServiceType(serviceType: String) -> SocialService?
  {
    switch serviceType
    {
      case "Twitter":
         return Twitter();
      case "Facebook":
         return Facebook()
      default:
         return nil;
    }
  }
}