Cari array untuk objek tipe yang disediakan

Saya memiliki serangkaian Hewan. Saya ingin mencarinya untuk tipe subkelas tertentu. Array Hewan hanya akan berisi satu dari setiap tipe subkelas. Saya sudah mencoba yang berikut ini, tetapi tidak berhasil. Saya mendapatkan kesalahan kompilasi, yang menyatakan: "animalType bukan tipe".

public static func getAnimal<T: Animal>(animalType: T.type) -> Animal {
    for animal in self.animals {
        if animal is animalType {
            return animal
        }
    }
}

Apakah ini mungkin di Swift?

Saya ingin menyebutnya seperti itu...

AnimalServices.getAnimal(Dog)

person lionpants    schedule 02.03.2015    source sumber
comment
Anda dapat melakukan cast if let sebagai suatu tipe dan jika gagal maka hewan tersebut bukan tipe tersebut   -  person Ian    schedule 02.03.2015
comment
Saya baru saja mencobanya. if let a = animal as animalType {} Kompiler masih mengeluh bahwa animalType bukan sebuah tipe. Apakah saya merusak sintaksisnya?   -  person lionpants    schedule 02.03.2015


Jawaban (4)


Berikut adalah contoh yang disederhanakan, perhatikan saya mengembalikan Hewan opsional karena pencarian mungkin gagal (kompiler tidak tahu bahwa Anda hanya akan memiliki satu hewan dari jenis itu):

class Animal {
    let name: String

    init(name: String) {
        self.name = name
    }
}

class Cat: Animal {
    init() {
        super.init(name: "Cat")
    }
}

class Dog: Animal {
    init() {
        super.init(name: "Dog")
    }
}

struct Zoo {
    static var animals: [Animal] = []

    static func getAnimal<T: Animal>(animalType: T.Type) -> Animal? {
        for animal in animals {
            if animal is T {
                return animal
            }
        }
        return nil
    }
}

Zoo.animals.append(Cat())

Zoo.getAnimal(Cat) // Returns the cat as optional
Zoo.getAnimal(Dog)

Sederhananya, T adalah tipe generik Anda. T.Type nyatakan bahwa Anda meneruskan tipe T sebagai parameter.

person Matteo Piombo    schedule 02.03.2015
comment
Saya sudah dekat. ;) Inilah yang saya inginkan. Terima kasih! - person lionpants; 02.03.2015
comment
Atau sebagai kalimat yang bagus: return animals.filter { $0 is T }.first. Meski kurang berkinerja. - person Rengers; 02.03.2015

Anda dapat menggunakan operator identitas === untuk memeriksa apakah tipe elemen array sama dengan tipe generik:

if animal.dynamicType === animalType {
    return animal
}
person Antonio    schedule 02.03.2015
comment
Tidak, kamu tidak bisa. Kompiler akan memunculkan kesalahan: operator biner '===' tidak dapat diterapkan ke operan bertipe 'Animal.Type' dan 'T' - person kellanburket; 02.03.2015
comment
@blacksquare Anda pasti melakukan sesuatu yang salah - ini berfungsi dengan baik di storyboard, dan terlebih lagi saya tidak menggunakan T dalam cuplikan kode itu... - person Antonio; 02.03.2015
comment
Saya baru saja menguji kode Anda di Swift 1.1 dan berhasil. Saya sedang menguji menggunakan Swift 1.2 dan muncul kesalahan--jadi berhati-hatilah di masa mendatang. Saya menggunakan sintaks yang saya gunakan untuk membandingkan dengan nilai string yang dikembalikan, yang merupakan perbandingan yang valid karena keduanya adalah String. Bagaimanapun, jawaban terbaik untuk pertanyaan ini adalah dengan memeriksa is T. - person kellanburket; 02.03.2015
comment
Solusi Anda berhasil, saya lebih suka @Matteo Piombo. Terima kasih! - person lionpants; 02.03.2015
comment
@lionpants: Ya, saya setuju, itulah cara yang benar untuk melakukannya - person Antonio; 02.03.2015
comment
@blacksquare Saya menguji pada 1.2 sekarang dan tampaknya berhasil - dan seperti yang dinyatakan di atas saya setuju dengan pernyataan terakhir Anda :) - person Antonio; 02.03.2015
comment
kamu benar--aku minta maaf. Setelah saya memuat ulang taman bermain, kesalahan itu berhenti terjadi. Saya awalnya memiliki contoh Anda menggunakan kesetaraan == dan kemudian mengalihkannya ke identitas ===--pasti ada beberapa bug xcode yang terbawa. ya. apa yang bisa kau lakukan? - person kellanburket; 02.03.2015

Anda tidak dapat menggunakan sintaks is atau as dengan tipe yang tidak diketahui. Jenis refleksi yang Anda cari dapat dilakukan menggunakan metode kindOfClass NSObject selama Animal adalah subkelas dari NSObject:

class Animal: NSObject {

    class func getAnimalOfType<T: Animal>(animals: [Animal], animalType: T.Type) -> Animal? {
        for animal in animals {
            if animal.isKindOfClass(animalType) {
                return animal
            }
        }
        return nil
    }

}

class Zebra: Animal { }
class Whale: Animal { }
var animals = [Zebra(), Whale()]
Animal.getAnimalOfType(animals, animalType: Zebra.self)

Jika Animal bukan subtipe dari NSObject, Anda selalu dapat melakukan ini--tetapi menurut saya ini agak rumit:

 if "\(animal.dynamicType)" == "\(animalType)" {
      return animal
 }
person kellanburket    schedule 02.03.2015

struct Test<T: Hashable> {

    static func test(t: Any) {
        println(t is T)
    }
}

Test<Int>.test(3)

Dalam contoh ini saya meneruskan tipe (Int dalam kasus saya, animalType dalam kasus Anda) ke struct dan variabel (Int saya (3), hewan Anda) sebagai parameter pengujian fungsi statis. Saya menggunakan T: Hashable, Anda ingin mengujinya dengan T: Animal.

person MirekE    schedule 02.03.2015