programing

신속한 수업 소개 및 일반론

codeshow 2023. 8. 10. 21:42
반응형

신속한 수업 소개 및 일반론

동적으로 생성하려고 합니다.class제네릭을 사용한 인스턴스 기반 유형이지만 수업 자기소개에 어려움을 겪고 있습니다.

다음은 질문입니다.

  • Obj-C와 동등한 스위프트가 있습니까?self.class?
  • 클래스를 사용하여 인스턴스화하는 방법이 있습니까?AnyClass으로부터 결과가 나온NSClassFromString?
  • 당신이 할 수 있는 방법이 있습니까?AnyClass또는 일반 매개 변수의 정보를 입력합니다.T(C#과 유사함)typeof(T)구문)

우선 스위프트는 다음과 같은 것입니다.[NSString class]이라.self(메타 유형 문서를 참조하십시오. 상당히 얇습니다.)

실은.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 실행 실패: 오류: 16:1: 오류: 메타타입 값으로 클래스 유형 '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이러한 클래스의 목표-공백 이름을 지시하는 구문입니다. 그렇지 않으면 각 클래스를 지정하는 공백 문자열을 알 수 없기 때문에 중요합니다.

이제 사용할 수 있습니다.NSClassFromStringZork 클래스 또는 Zilk 클래스를 만드는 것은 NSO 객체로 입력할 수 있고 나중에 충돌하지 않을 수 있다는 것을 알기 때문입니다.

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

그리고 그것은 되돌릴 수 있습니다.println(NSStringFromClass(anObject.dynamicType))작동하기도 합니다.


최신 버전:

    if let aClass = NSClassFromString("Zork") as? NSObject.Type {
        let anObject = aClass.init()
        print(anObject) // "I am a Zork"
        print(NSStringFromClass(type(of:anObject))) // Zork
    }

문서를 제대로 읽고 있다면 인스턴스를 처리하고 예를 들어 지정된 개체와 동일한 유형의 새 인스턴스를 반환하고 유형을 init()로 구성할 수 있다면 다음 작업을 수행할 수 있습니다.

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

String으로 빠르게 테스트했습니다.

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

그것은 잘 작동했습니다.

인스위프트 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")

빙고 "make Foo"에는 Foo 인스턴스가 포함되어 있습니다.

단점은 클래스가 FactoryObject에서 파생되어야 하며 글로벌 함수 "mapClass"에 의해 클래스 맵에 자동으로 삽입되도록 Obj-C +initialize 메서드가 있어야 한다는 것입니다.

다음은 수락된 답변과 유사한 클래스 계층 구현을 보여주는 또 다른 예로, 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

언급URL : https://stackoverflow.com/questions/24049673/swift-class-introspection-generics

반응형