সুইফ্ট ক্লাসের আত্মবিজ্ঞাপন এবং জেনারিকস


121

আমি classজেনেরিকগুলি ব্যবহার করে একটি উদাহরণ ভিত্তিক প্রকারটি গতিশীলরূপে তৈরি করার চেষ্টা করছি , তবে আমি শ্রেণি অন্তঃসংশোধনে অসুবিধায় পড়ছি।

প্রশ্নগুলি এখানে:

  • ওবজ-সি এর সাথে একটি সুইফট-সমতুল্য কি আছে self.class?
  • AnyClassফলাফলটি ব্যবহার করে কোনও শ্রেণি ইনস্ট্যান্ট করার কোনও উপায় আছে কি NSClassFromString?
  • AnyClassজেনেরিক প্যারামিটার থেকে কঠোরভাবে তথ্য পাওয়ার বা টাইপ করার কোনও উপায় আছে কি T? (সি # এর typeof(T)সিনট্যাক্সের মতো)

2
stackoverflow.com/a/24069875/292145 সুইফ্ট প্রতিবিম্ব এপিআইতে কিছু ইঙ্গিত দেয়।
ক্লাস

5
উদ্দেশ্য-সি এর দ্রুত সুইচ আই-তে বিশ্বাস self.classহয়ে যাবেself.dynamicType.self
ফিলিপ হারম্যানস

1
উদাহরণস্বরূপ পদ্ধতিতে, এখানে কোনও self.dynamicType.foo()

উত্তর:


109

ওয়েল, এক জন্য, সুইফ্ট সমতুল্য [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()

হুম ... ত্রুটি বলে:

খেলার মাঠের সম্পাদন ব্যর্থ হয়েছে: ত্রুটি:: 16: 1: ত্রুটি: একটি মেটাটাইপ মান সহ শ্রেণীর ধরণের 'এক্স' অবজেক্ট তৈরি করার জন্য একটি '@ প্রয়োজনীয়' ইনিশিয়ালাইজারের প্রয়োজন

 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আমাকে খেলার মাঠ একটি ত্রুটি দেয়।


1
মেটাটাইপ ডক্সে আপনার লিঙ্কের জন্য ধন্যবাদ! প্রকারভেদগুলির দিকটি আমি সম্পূর্ণভাবে উপেক্ষা করেছি, দোহ!
এরিক

14
আপনি ব্যবহার করতে পারেন .Typeবা .Protocolপরিবর্তনশীল ঘোষণাপত্রে, উদাহরণস্বরূপlet myObject: MyObject.Type = MyObject.self
সুলতান

1
সুলতান: সুতরাং মাইওবজেক্ট.টাইপ একটি ঘোষণা তবে মাইওবজেক্ট.সেলফ একটি ফ্যাক্টরি পদ্ধতি (বলা যেতে পারে) এবং মাইওবজেক্ট একটি ফ্যাক্টরি পদ্ধতির রেফারেন্স সম্বলিত একটি পরিবর্তনশীল। মাইওবজেক্ট () কলটি ক্লাস মাইওবজেক্টের একটি উদাহরণ তৈরি করবে। মায়োবজেক্ট ভেরিয়েবলের নামটি মাইঅবজেক্টফ্যাক্টরি হলে এটি আরও ভাল উদাহরণ হতে পারে?
বুটচক

2
@এর আগে requiredমুছে ফেলা উচিত
ফুজিয়ানজিন 6471

49

কিভাবে ব্যবহার করবেন তা এখানে 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এই শ্রেণীর উদ্দেশ্য-সি মুগুড নামটি লেখার জন্য বিশেষ বাক্য গঠনটির ব্যবহার লক্ষ্য করুন ; এটি অত্যন্ত গুরুত্বপূর্ণ, কারণ অন্যথায় আমরা প্রতিটি শ্রেণিকে মনোনীত মংড স্ট্রিং জানি না।

এখন আমরা NSClassFromStringজোরক ক্লাস বা জিল্ক শ্রেণি তৈরি করতে ব্যবহার করতে পারি, কারণ আমরা জানি আমরা এটি এনএসওজেক্ট হিসাবে টাইপ করতে পারি এবং পরে ক্রাশ না করে:

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
    }

10
@objc(ClassName)বিট জন্য upvote । আমি @objcগুণাবলী সম্পর্কে জানতাম তবে তা নয় যে আপনি শ্রেণির নাম সম্পর্কে কোনও ইঙ্গিতও দিতে পারেন।
এরিক

1
6 বছরের লিখিত হিসাবে এখনও কম-বেশি কাজ করে এমন দুর্দান্ত সমাধান। খেলার মাঠের জন্য জিজ্ঞাসা করা হয়েছে মাত্র দু'টি ছোটখাটো টুইট: as! NSObject.Typeপ্রথম লাইনে এবং aClass.init()দ্বিতীয়টিতে
কাজি

13

যদি আমি ডকুমেন্টেশনটি সঠিকভাবে পড়ছি, আপনি যদি উদাহরণগুলির সাথে ডিল করেন এবং উদাহরণস্বরূপ আপনার দেওয়া বস্তুর চেয়ে একই ধরণের একটি নতুন উদাহরণ ফিরে আসতে চান এবং টাইপটি কোনও init দিয়ে তৈরি করা যেতে পারে () আপনি করতে পারেন:

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

আমি দ্রুত স্ট্রিংয়ের মাধ্যমে এটি পরীক্ষা করেছি:

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

যা ভাল কাজ করেছে।


1
হ্যাঁ, dynamicTypeআমি সেখানে প্রত্যাশা মতো কাজ করি। তবে আমি ধরণের তুলনা করতে অক্ষম। আসল বড় ব্যবহার জেনেরিক্স সহ, তাই আমার মতো Generic<T>এবং এর ভিতরেও কিছু থাকতে পারে if T is Double {...}। মনে হচ্ছে দুর্ভাগ্যজনকভাবে সম্ভব নয়।
এরিক

1
@ সিলো আপনি কি কখনও সাধারণভাবে জিজ্ঞাসার উপায় খুঁজে পেয়েছেন যে দুটি বস্তু একই শ্রেণীর?
ম্যাট

1
@ ম্যাটটি মার্জিতভাবে নয়, না আমিও করিনি। যাইহোক, আমি একটি তৈরি করতে সক্ষম হন Defaultableপ্রোটোকল যা সি # 'গুলি অনুরূপ কাজ করে defaultমত ধরনের জন্য কীওয়ার্ডটি এবং যথাযথ এক্সটেনশন Stringএবং Int। জেনেরিক সীমাবদ্ধতা যোগ করে T:Defaultable, আমি তর্ক করতে পারলাম কিনা তর্ক করতে পারলাম is T.default()
এরিক

1
@ সিলো চালাক; আমি সেই কোডটি দেখতে চাই! আমি এটি গ্রহণ করি যে এটি "হ'ল" ব্যবহারের ক্ষেত্রে অদ্ভুত সীমাবদ্ধতার কাছাকাছি যায়। আমি এই সীমাবদ্ধতাগুলিতে এবং ক্লাসের অন্তঃকরণের সাধারণ অভাবের জন্য একটি বাগ ফাইল করেছি। আমি এনএসএসটিংফ্রমক্লাস ব্যবহার করে স্ট্রিংগুলির সাথে তুলনা শেষ করেছি, তবে অবশ্যই এটি কেবল এনএসবজেক্ট বংশধরের জন্য কাজ করে।
ম্যাট

1
@ ম্যাট দুর্ভাগ্যক্রমে এটি এর চেয়ে বেশি চতুর বলে মনে হচ্ছে কারণ আপনার এখনও value is String.default()... ইত্যাদি করতে হবে যা আপনি কেবল এর value is Stringপরিবর্তে শেষ করবেন ।
এরিক

13

ইন দ্রুতগতি 3

object.dynamicType

অবচয় করা হয়।

পরিবর্তে ব্যবহার করুন:

type(of:object)

7

তুলনা প্রকারের দ্রুত বাস্তবায়ন

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

দ্রষ্টব্য: লক্ষ্য করুন যে এটি প্রোটোকলগুলির সাথেও কাজ করে যাতে অবজেক্টটি প্রসারিত হতে পারে বা নাও পারে


1

অবশেষে কাজের কিছু পেলাম। এটি কিছুটা অলস তবে এমনকি এনএসক্লাসফ্রম স্ট্রিং () রুটটি আমার পক্ষে কার্যকর হয়নি ...

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")

এবং বিঙ্গো, "মেকফু" তে একটি ফু দৃষ্টান্ত রয়েছে।

খারাপ দিকটি হ'ল আপনার ক্লাসগুলি অবশ্যই ফ্যাক্টরিওজেক্ট থেকে নেওয়া উচিত এবং তাদের অবশ্যই ওবজে-সি + ইনিশিয়াল পদ্ধতি করা উচিত যাতে আপনার ক্লাসটি স্বয়ংক্রিয়ভাবে ক্লাস মানচিত্রে গ্লোবাল ফাংশন "ম্যাপক্লাস" দ্বারা সন্নিবেশিত হয়।


1

এখানে আরও একটি উদাহরণ রয়েছে শ্রেণিবদ্ধ শ্রেণিবদ্ধ বাস্তবায়ন, যা সুইফটের প্রথম প্রকাশের জন্য আপডেট হওয়া স্বীকৃত উত্তরের অনুরূপ।

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

2
ভেরিয়েবলটি সুপারক্লাসের ধরণ হলে এই কৌশলটি সঠিকভাবে কাজ করে না। উদাহরণস্বরূপ, প্রদত্ত var x: NamedItem.Type, যদি আমি এটি বরাদ্দ করি x = Folder.Typeতবে x()একটি নতুন NamedItemনয়, একটি প্রদান করে Folder। এটি অনেক অ্যাপ্লিকেশনগুলির জন্য অকেজো কৌশলটি রেন্ডার করে। আমি এই একটি বাগ বিবেচনা ।
ফ্যাটম্যান

1
আসলে আপনি আমি আপনাকে এই কৌশল ব্যবহার করে সেটি কি মনে করতে পারি না stackoverflow.com/questions/26290469/...
possen
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.