Свифт классе самоанализ & дженериков



Я пытаюсь динамически создать class тип на основе экземпляра с использованием дженериков, однако я сталкиваюсь с трудностями с самоанализом класса.



вот вопросы:




  • есть ли Swift-эквивалент Obj-C self.class?

  • есть ли способ создать экземпляр класса с помощью AnyClass в результате NSClassFromString?

  • есть ли способ сделать AnyClass или в противном случае введите информацию строго из общего параметра T? (Похоже на C# ' s typeof(T) синтаксис)

505   7  

7 ответов:

Ну, во-первых, быстрый эквивалент [NSString class] и .self (см. Metatype docs, хотя они довольно тонкие).

в самом деле NSString.class не работает! Вы должны использовать NSString.self.

let s = NSString.self
var str = s()
str = "asdf"

точно так же, с быстрым классом я пробовал...

class MyClass {

}

let MyClassRef = MyClass.self

// ERROR :(
let my_obj = MyClassRef()

Хм ... ошибка говорит:

Playground execution failed: error:: 16:1: error: построение объекта класса типа ' X ' со значением метатипа требует инициализатор '@required'

 Y().me()
 ^
 <REPL>:3:7: note: selected implicit initializer with type '()'
 class X {
       ^

мне потребовалось некоторое время, чтобы понять, что это значит... оказывается, он хочет, чтобы класс имел @required init()

class X {
    func me() {
        println("asdf")
    }

    required init () {

    }
}

let Y = X.self

// prints "asdf"
Y().me()

некоторые врачи относятся к этому как .Type, а MyClass.Type дает мне ошибку на детской площадке.

вот как использовать NSClassFromString. Вы должны знать суперкласс того, что вы собираетесь в конечном итоге. Вот суперкласс-подкласс пара, которая знает, как описать себя для println:

@objc(Zilk) class Zilk : NSObject {
    override var description : String {return "I am a Zilk"}
}

@objc(Zork) class Zork : Zilk {
    override var description : String {return "I am a Zork"}
}

обратите внимание на использование специального @obj синтаксис, чтобы диктовать Objective-C munged имя этих классов; это очень важно, потому что в противном случае мы не знаем munged строку, которая обозначает каждый класс.

теперь мы можем использовать NSClassFromString чтобы сделать класс Zork или Zilk класс, потому что мы знаем, что мы можем ввести его как NSObject и не сбой позже:

let aClass = NSClassFromString("Zork") as NSObject.Type
let anObject = aClass()
println(anObject) // "I am a Zork"

и это обратимо; println(NSStringFromClass(anObject.dynamicType)) тоже работает.

Если я правильно читаю документацию, если вы имеете дело с экземплярами и, например, хотите вернуть новый экземпляр того же типа, что и объект, который вам был предоставлен, и тип может быть построен с помощью init() вы можете сделать:

let typeOfObject = aGivenObject.dynamicType
var freshInstance = typeOfObject()

я быстро проверил его с строку:

let someType = "Fooo".dynamicType
let emptyString = someType()
let threeString = someType("Three")

, который работал хорошо.

на swift 3

object.dynamicType

устарела.

вместо этого использовать:

type(of:object)

быстрая реализация сравнения типов

protocol Decoratable{}
class A:Decoratable{}
class B:Decoratable{}
let object:AnyObject = A()
object.dynamicType is A.Type//true
object.dynamicType is B.Type//false
object.dynamicType is Decoratable.Type//true

Примечание: заметить, что он также работает с протоколами объект может или не может продлить

наконец-то работать. Его немного ленивый, но даже маршрут NSClassFromString() не работал для меня...

import Foundation

var classMap = Dictionary<String, AnyObject>()

func mapClass(name: String, constructor: AnyObject) -> ()
{
    classMap[name] = constructor;
}

class Factory
{
    class func create(className: String) -> AnyObject?
    {
        var something : AnyObject?

        var template : FactoryObject? = classMap[className] as? FactoryObject

        if (template)
        {
            let somethingElse : FactoryObject = template!.dynamicType()

            return somethingElse
        }

        return nil
    }
}


 import ObjectiveC

 class FactoryObject : NSObject
{
    @required init() {}
//...
}

class Foo : FactoryObject
{
    class override func initialize()
    {
        mapClass("LocalData", LocalData())
    }
    init () { super.init() }
}

var makeFoo : AnyObject? = Factory.create("Foo")

и бинго, "makeFoo" содержит экземпляр Foo.

недостатком является то, что ваши классы должны выводиться из FactoryObject, и они должны иметь метод инициализации Obj-C+, чтобы ваш класс автоматически вставлялся в карту класса глобальной функцией "mapClass".

вот еще один пример, показывающий реализацию иерархии классов, аналогичную принятому ответу, обновленному для первого выпуска Swift.

class NamedItem : NSObject {
    func display() {
        println("display")
    }

    required override init() {
        super.init()
        println("base")
    }
}

class File : NamedItem {
    required init() {
        super.init()
        println("folder")
    }
}

class Folder : NamedItem {
    required init() {
        super.init()
        println("file")
    }
}

let y = Folder.self
y().display()
let z = File.self
z().display()

выводит такой результат:

base
file
display
base
folder
display

Comments

    Ничего не найдено.