2016-04-10 6 views
2

Ben derleyici hatası alıyorum: (hata İkili operatör '===' iki 'T' operandların için uygulanamaz) T.Genel bir tür için === operatörüne izin vermek için hangi protokolün genişletilmesi gerekiyor?</p> <blockquote> <p>Binary operator '===' cannot be applied to two 'T' operands</p> </blockquote> T jenerik türüdür <p>ve ben sadece iki öğe kıyaslıyorum:

Bu yüzden === operatörünün T protokolünü kullanarak T üzerinde kullanılabileceğini söylemem gerektiğini farz ediyorum. == olsaydı Equatable kullanırdım, ancak kimlik karşılaştırması için ne kullanacağımı göremiyorum.

Ya da bir iş var mı?

DÜZENLEME: Burada

problemi gösteren bir kod örneklem parçasıdır. Sınıf oluşturulduğunda derleme hatasına neden olan 'AnyObject' ekledim. 'AnyObject' kaldırılırsa, '===' üzerinde bir hataya neden olur.

import Foundation 

protocol Messenger : AnyObject { 
    func notify(); 
} 

class PostOffice<T : AnyObject> { 
    var messengers : [T] = [] 

    func addMessenger(messenger : T) { 
     messengers.append(messenger) 
    } 

    func deleteMessenger(messenger : T) { 
     for i in 0 ..< messengers.count { 
      if messengers[i] === messenger { // error if AnyObject not used 
       messengers.removeAtIndex(i) 
       return 
      } 
     } 
    } 

    func handleDelivery(messenger : T) {} // to be overridden 

    func deliver() { 
     for messenger in messengers { 
      handleDelivery(messenger) 
     } 
    } 
} 

let p : PostOffice<Messenger> = PostOffice<Messenger>() // error if AnyObject used 

bu durumda hatadır:

Using 'Messenger' as a concrete type conforming to 'AnyObject' is not support.

+0

derleme hatası nedir? – nhgrif

+0

Ve bu arada, "deleteMessenger" inizde, aynı nesne birden çok kez varsa, içinde bir kilitlenme veya hata var. Ön tarafa çalışmalısın. – nhgrif

cevap

2

Eğer === tanımlanır yolu bir göz atacak olursak:

public func ===(lhs: AnyObject?, rhs: AnyObject?) -> Bool 

ve

public func ===<L : AnyCollectionType, R : AnyCollectionType>(lhs: L, rhs: R) -> Bool 

yapabilirsiniz’e ihtiyacınız olduğuna inanıyorum, AnyObject veya AnyCollectionType'a uygundur. Örneğin:

func f<T : AnyObject>(a: T, b: T) -> Bool { 
    return a === b 
} 

veya

func f<T : AnyCollectionType>(a: T, b: T) -> Bool { 
    return a === b 
} 
+0

Şimdi, bu yüzden mobil kontrol edemez am ama tasavvur, biz (Equatable' 'gibi)' === 'işlevi vardır bir protokol yapabiliriz ardından' uzatmak AnyObject' ve 'AnyCollectionType' protokolüne uyacak şekilde , sağ? – nhgrif

+0

Maalesef, 'Başka bir yerde kullanmayı denediğimde' ProtokolB 'protokolü' AnyObject 'protokolüne uygun bir beton türü olarak kullanılma hatası aldım. Ama bu farklı bir konu olabilir. – rghome

+0

Bu hatayı veren kodu gönderir misiniz? – ABakerSmith

1

Sen mantıklı değil bir şekilde jeneriği ve protokolleri karıştırma ediyoruz.

class PostOffice<T : AnyObject> { 

Bu

bazı belirli tip etrafında ambalaj olmak Postoffices istediğiniz anlamına gelir. "Böyle bir protokole uyan herhangi bir tür" değil, bir ve tam olarak bir tür. Tamam sorun değil.

let p : PostOffice<Messenger> = PostOffice<Messenger>() // error if AnyObject used 

Bu Messenger uygun olur her türlü sarar bir PostOffice olmak p istiyorum diyor. Eh, PostOffice olmak istediğini söylemediğin şey bu değildi. Tipik uzman olmasını istediğini söylemiştin. Peki bu hangisi? senin adlandırma dayanarak

, herhangi Messenger kabul etmek PostOffice istiyorum gerçekten size varsayıyorum. Bu iyi, ama o zaman genel olmamalı:, size aslında PostOffice olmayan Messengers üzerinde çalışmak istediğiniz sesini veren yerde notify() kullanmadığınız söyledi

class PostOffice { 
    var messengers : [Messenger] = [] 

    func addMessenger(messenger : Messenger) { 
     messengers.append(messenger) 
    } 

    func deleteMessenger(messenger : Messenger) { 
     for i in 0 ..< messengers.count { 
      if messengers[i] === messenger { // error if AnyObject not used 
       messengers.removeAtIndex(i) 
       return 
      } 
     } 
    } 
    func handleDelivery(messenger : Messenger) {} // to be overridden 

    func deliver() { 
     for messenger in messengers { 
      handleDelivery(messenger) 
     } 
    } 
} 

. (Ne kadar yararlı olduğuna emin değilsiniz, ama yazdığınız gibi görünüyor).Bu da, iyi, ama o zaman sen ile PostOffice uzmanım bazı gerçek tip (bir protokol) gerekir: Gerçekten PostOffice uzman gerektiği anlamına ederse

class SomeMessenger: Messenger { 
    func notify() {} 
} 

let p = PostOffice<SomeMessenger>() 

, ancak herhangi bir kabul etmek, bu durumda istiyorum .

final class AnyMessager: Messenger { 
    let _notify:() -> Void 
    init(messenger: Messenger) { 
     _notify = messenger.notify 
    } 
    func notify() { _notify() } 
} 

let p = PostOffice<AnyMessager>() 

(Bu, pek çok Swift protokol konularında çözüm, ancak bu durumda doğru gelmiyor I: Eğer Messenger sarar somut bir türü yaratmak, böylece Messenger tür, o zaman type-erasure gerek PostOffice'un gerçekten istediği için şüphelendiğin bir Messenger. Ama ben senin PostOffice tipini gerçekten anlamıyorum. Jeneriği gerçekten çok Swifty hissetmeyen soyut sınıflarla birleştirir. Ben gerçekten bu tür yeniden tasarlamak istiyor şüpheli.)

Sen this implementation of an Observable ilginizi çekebilir. === veya notify yöntemini gerektirmeden dinleyicileri kaydetmenin ve kaldırmanın farklı bir yolunu gösterir. <: AnyObject T> `` kullanırken

+0

Tüm kodu dökmedim. Gerçekte, PostOffice, örneğini değil, soyut bir sınıf olarak kullanılır. Ona eklenen dinleyicileri yönetir ve başka bir mantık sağlar (gösterilmemiştir). Yani 'teslim et' diğer şeyleri yapar, ancak her T türüne özgü şeyler türetilmiş sınıflarda ele alınır. 'Messenger', kötü bir şekilde adlandırılmıştır, ancak teslimatları alan bir şeyin protokolünün özel bir örneğidir. Başkaları var. Ortak olan tek şey, kimlik karşılaştırması yapmam gerektiğidir, bu yüzden '===' kontrolüne ihtiyacım var. Önerilerinizi okuyacağım ve yeniden okuyabilecek miyim? Teşekkürler! – rghome