2016-04-07 55 views
1

我想实现仅支持类支持的协议的方法。为此,我已经定义了一个协议:Swift:限制类只支持协议

protocol TestProt { 
    func testMe() -> String 
} 

让我们做一个类声明:

class TestClass: TestProt { 
    func testMe() -> String { 
     return "test" 
    } 
} 

但是,我怎么能实现寄存器类别,只支持类TestProt?

class FabricaClass { 
    // it is func take any classes :(
    func registerMe(context: MyContext, class: AnyClass) -> String { 
    } 
    // i want something like this =) 
    // to the method took only classes supported protocols 
    // but it don't work for swift... 
    func registerMe(context: MyContext, class: AnyClass <TestProt>) -> String { 
    } 

} 

UPD:答案

protocol TestProt { 
    static func testMe() -> String 
} 

class TestClass: TestProt { 
    class func testMe() -> String { 
     return "test" 
    } 
} 

class MyContext { 
} 

class FactoryClass { 
    init<T: TestProt>(context: MyContext, regClass: T.Type) { 
     regClass.testMe() 
    } 
} 

let context = MyContext() 
let factory = FactoryClass(context: context, regClass: TestClass.self) 

感谢@dfri

+0

值得看http://stackoverflow.com/a/24051850/2710486 – zcui93

回答

3

你需要在你的函数一个泛型类型,并添加类型约束这个泛型类型,其中类型约束确保类型利用该功能的符合使用类型约束的协议。例如: -

/* add :class keyword to constrain this protocol only 
to be conformable to by class types */ 
protocol ProtocolOnlyIntendedForClasses: class { 
    func foo() -> String 
    init() // to make use of metaType for initialization in generic function 
} 

class Foo: ProtocolOnlyIntendedForClasses { 
    func foo() -> String { 
     return "foo" 
    } 
    required init() { } 
} 

/* function taking class type objects that conforms 
    to ProtocolOnlyIntendedForClasses */ 
func bar<T: ProtocolOnlyIntendedForClasses>(foo: T) -> String { 
    return foo.foo() 
} 

/* as above, but making use of metatype representation 
    of generic T rather than an instance of it */ 
func barWithMetaType<T: ProtocolOnlyIntendedForClasses>(fooMetaType: T.Type) -> String { 

    // .. 

    return fooMetaType.init().foo() 
} 

/* example usage */ 
let foo = Foo() 
let baz = bar(foo) 
let bax = barWithMetaType(Foo.self) 
print(baz, bax) // foo foo 

当我们访问与使用T.Type一元类型的T类型。

应用到您的具体例如:然而

// ... 

class FabricaClass { 

    // ... 

    // as specified in comments, you want the class (meta)type, 
    // rather than an instance of it 
    func registerMe<T: TestProt>(context: MyContext, someMetaType: T.Type) -> String { 

     // ... 

     return someMetaType.init().testMe() 
      // given that you added blueprint for 'init()' in protocol TestProt 
    } 

} 

注意的是,使用元类型(someMetaTyperegisterMe(..)上述功能)是相当有限的,并且不等同于使用静态(编译时已知的)类型。


有关详细信息,请参阅

+0

不,我需要获得**类**的方法,而不是Instans –

+0

@EvGeniyIlyin更新的答案_metatypes_类型约束泛型而不是类型的实例约束泛型。 – dfri

+0

谢谢!你救我=) –

0

你试试这个?

func registerMe(context: MyContext, class: TestProt) -> String { 
} 
0

我不知道你是否真的希望它仅限于类,还是你意思是:

我怎么能实现注册类,只有类型支持 TestProt?

无论如何,如果你想限制类,请参阅@ dfri的回复。对于问题的其余部分有两种方法。有一般方法:

fund registerMe<T: TestProt>(context: MyContext, class:T) -> String {} 

其中T采取它通过的类型。例如,如果此方法要返回与类相同类型的类型(而不是String),则编译器将知道正在返回TestClass实例。但另一种方式:

func registerMe(context: MyContext, class:TestProt) -> String {} 

你铸造TestProt,因此而dynamicType仍将TestClass在运行时,没有办法为传递给方法,为您返还相同种类。您只能将实例作为符合TestProt的实例发回。然后你需要回到实际的课堂。