Swift yerel temel sınıfı veya NSObject


105

Biraz test ettim Swift ile bir swizzling ve yalnızca NSObject süper sınıf olduğunda (doğrudan veya daha ileri) veya '@objc' dekorasyonunu kullanarak çalıştığını gördüm. Aksi takdirde, C ++ gibi statik ve vtable gönderme stilini izleyecektir.

Cocoa / NSObject temel sınıfı olmadan bir Swift sınıfı tanımlamak normal midir? Endişeleniyorsam, bu, yöntem durdurma ve çalışma zamanı iç gözlemi gibi Objective-C dinamizminin çoğundan vazgeçmek anlamına gelir.

Dinamik çalışma zamanı davranışı, özellik gözlemcileri, Temel Veriler, Yöne Yönelik Programlama , Yüksek Sıralı Mesajlaşma , analitik ve günlükleme çerçeveleri ve benzeri özelliklerin merkezinde yer alır.

Objective-C'nin yöntem çağırma tarzını kullanmak, bir yöntem çağrısına yaklaşık 20 makine kodu işlenen ekler, bu nedenle belirli durumlarda ( küçük gövdeli yöntemlere yapılan birçok sıkı çağrı ) C ++ stili statik ve vtable gönderimi daha iyi performans gösterebilir.

Ancak genel 95-5 kuralı göz önüne alındığında ( performans kazanımlarının% 95'i kodun% 5'ini ayarlamadan gelir ), güçlü dinamik özelliklerle başlamak ve gerektiğinde sertleşmek mantıklı değil mi?


İlgili: Swift, yön odaklı programlamayı destekliyor mu? stackoverflow.com/a/24137487/404201
Jasper Blues

Yanıtlar:


109

NSObject'in alt sınıfları olan Swift sınıfları:

  • Objective-C sınıflarının kendileridir
  • objc_msgSend()yöntemlerine (çoğu) çağrı yapmak için kullanın
  • Yöntem uygulamaları için (çoğu) Objective-C çalışma zamanı meta verilerini sağlar

NSObject'in alt sınıfları olmayan Swift sınıfları:

  • Objective-C sınıflarıdır, ancak NSObject uyumluluğu için yalnızca birkaç yöntem uygular
  • objc_msgSend()yöntemlerine çağrı yapmak için kullanmayın (varsayılan olarak)
  • yöntem uygulamaları için Objective-C çalışma zamanı meta verilerini sağlamayın (varsayılan olarak)

NSObject'in Swift'de alt sınıflara ayrılması size Objective-C çalışma zamanı esnekliği ve aynı zamanda Objective-C performansı sağlar. NSObject'den kaçınmak, Objective-C'nin esnekliğine ihtiyacınız yoksa performansı artırabilir.

Düzenle:

Xcode 6 beta 6 ile dinamik öznitelik görünür. Bu, Swift'e bir yöntemin dinamik gönderimi kullanması gerektiğini ve dolayısıyla müdahaleyi destekleyeceğini söylememizi sağlar.

public dynamic func foobar() -> AnyObject {
}

1
Swift objc_msgSend yerine ne tür bir gönderim kullanıyor? Statik mi?
Bill

12
Swift objc_msgSend gönderimini, sanal tablo gönderimini, doğrudan gönderimi veya satır içi gönderimi kullanabilir.
Greg Parker

statik: 1.1ns'den az. vtable 1.1ns, msgSend 4.9ns. . (Elbette donanıma bağlıdır). . Görünüşe göre 'saf' Swift, sistem düzeyinde programlama için harika bir dil yapıyor, ancak uygulamalar için dinamik özelliklerden vazgeçme konusunda isteksiz olurdum, ancak derleyiciye, Çöp Toplama ve ARC'de olduğu gibi geçerlerse mutlu olurdum. . . Statik dağıtımın çok çekirdekli sistemlerde daha iyi dal tahminine (ve dolayısıyla performansa) izin verdiğini duydum. Doğru?
Jasper Blues

"NSObject'in alt sınıfları olmayan Swift Sınıfları, Objective-C sınıflarıdır" - belirttiğiniz yeri bulduğunuza bir bağlantı sağlayabilir misiniz?
Matt S.

1
Özet olarak, Objective C koduyla iletişim kurmam gerekirse, Swift'de yalnızca NSObject alt sınıfını kullanmalıyım?
MobileMon

14

Ayrıca, bir Swift sınıfını NSObject'e dayandırırsanız, kodlama hatalarını gizleyebilecek bazı beklenmedik çalışma zamanı davranışları gördüm. İşte bir örnek.

NSObject'i temel almadığımız bu örnekte, derleyici testIncorrect_CompilerShouldSpot'ta "... 'Sınıfım' 'MirrorDisposition'a dönüştürülemez.

class MyClass {
  let mString = "Test"

  func getAsString() -> String {
    return mString
  }

  func testIncorrect_CompilerShouldSpot() {
    var myString = "Compare to me"
      var myObject = MyClass()
      if (myObject == myString) {
        // Do something
      }
  }

  func testCorrect_CorrectlyWritten() {
    var myString = "Compare to me"
      var myObject = MyClass()
      if (myObject.getAsString() == myString) {
        // Do something
      }
  }
}

Üzerinde temel nereye Bu örnekte, NSObject , derleyici değil testIncorrect_CompilerShouldSpot hatası nokta:

class myClass : NSObject {
  let mString = "Test"

  func getAsString() -> String {
    return mString
  }

  func testIncorrect_CompilerShouldSpot() {
    var myString = "Compare to me"
      var myObject = MyClass()
      if (myObject == myString) {
        // Do something
      }
  }

  func testCorrect_CorrectlyWritten() {
    var myString = "Compare to me"
      var myObject = MyClass()
      if (myObject.getAsString() == myString) {
        // Do something
      }
  }
}

Sanırım ahlaki, gerçekten yapmanız gereken yerde NSObject'e dayanmaktır!


1
Bilgi için teşekkürler.
Jasper Blues

13

Dil referansına göre, sınıfların herhangi bir standart kök sınıfın alt sınıfına girmesine gerek yoktur, bu nedenle gerektiğinde bir üst sınıfı dahil edebilir veya çıkarabilirsiniz.

Sınıf bildiriminden bir üst sınıf çıkarılmasının, herhangi bir türden örtük bir temel üst sınıf atamadığını unutmayın. Bağımsız bir sınıf hiyerarşisinin kökü olacak olan temel bir sınıfı tanımlar.

Dil referansından:

Swift sınıfları, evrensel bir temel sınıftan miras almaz. Bir üst sınıf belirtmeden tanımladığınız sınıflar, üzerine inşa edebileceğiniz temel sınıflar haline gelir.

superSüper sınıf (yani temel sınıf) olmayan bir sınıftan başvurmaya çalışmak derleme zamanı hatasıyla sonuçlanacaktır.

'super' members cannot be referenced in a root class

1
Evet. Bir proje bağlamında bir Cocoa Veya Cocoa Touch kaynak dosyası oluşturmaya çalışırsanız, alt sınıfı eklediğiniz form aslında sınıfı boş bırakırken oluşturmanızı engeller. Üst sınıfı, daha sonra oluşturulduktan sonra kaldırabilirsiniz.
Cezar

1
Teşekkürler. Statik ve vtable gönderimini kullanmak, sistem programlaması veya performans ayarı için mantıklıdır. Yerli Kakao ile tutarlılık için, varsayılanın dinamik olması gerektiğini düşünüyorum . (Birisi beni başka türlü ikna edemediği sürece, bu sorudan dolayı)
Jasper Blues

1

Swift verilerinin büyük çoğunluğunun objc . Yalnızca Objective C altyapısıyla iletişim kurması gereken parçalar açıkça bu şekilde işaretlenecektir.

Dile çalışma zamanı iç gözleminin ne ölçüde ekleneceğini bilmiyorum. Yönteme müdahale, muhtemelen ancak yöntem açıkça izin verirse mümkün olacaktır. Bu benim tahminim, ancak yalnızca Apple'daki dil tasarımcıları gerçekten nereye gittiklerini biliyor.


Bana göre dinamizmi varsayılan yapmak mantıklıdır (NSObject'i genişletmek, '@objc' dekorasyonunu veya başka bir yaklaşımı kullanarak). Görünüşe göre temel sınıf olmadığında, Swift daha iyi performans gösteren statik / vtable gönderimini tercih edecek, ancak çoğu durumda bu gerekli olmayacak. . (Kazançların% 90'ı kodun% 10'unu ayarlamadan gelir). Umudum, Objective-C'nin dinamizmiyle tutarlılığın, tercih etmekten ziyade devre dışı bırakılmasıdır.
Jasper Blues

Dilin tasarlanma şekli, isteğe bağlı seçmedir. Bildiğimiz kadarıyla, gelecekte doğal olarak objc olmayan sistem API'leri de eklenecektir. Orta / uzun vadede, var olan kitaplıkları, objc'de objc olmayan koda çağıran ince bir uyumluluk katmanı ile objc olmayan koda bile geçirebilirler. Sadece bilmiyoruz. Bundan educated guessesbirkaç yıl sonra muhtemelen kazanabiliriz . Ama şu an için sadece büyük bir soru işareti.
Analog Dosya

@JasperBlues Dinamizmin çoğu zaman gerekli olmadığını ve varsayılan olarak performansa sahip olmayı tercih ettiğimi ve ardından dinamik davranışı tercih ettiğimi iddia ediyorum. Her biri için kendi sanırım :)
Lance

@Lance Hmmmm. Olabilir. Hala endişelerim var: gözlemciler, AOP, test alay etme çerçeveleri, analitik çerçeveler vb. ve performansla ilgili olan şey, kazançların% 90'ının% 10'u ayarlamadan kaynaklanmasıdır. . işte mantığım bu - bu% 10 vakaları dahil edin. AOP'nin iOS kurumsal uygulamaları için önemli olacağını düşünüyorum, ancak C ++ 'da olduğu gibi bir derleyici aracı kullanılarak yapılabilir. . kesinlikle oyunlar, bilimsel bilgi işlem, grafikler vb. geliştiriciler daha fazla performansı memnuniyetle karşılayacak :)
Jasper Blues

1

Aşağıdakiler Apple'ın Swift-eBook'undan kopyalanır ve sorunuza uygun bir cevap verir:

Temel Sınıf Tanımlama

Başka bir sınıftan miras almayan herhangi bir sınıf, temel sınıf olarak bilinir.

Swift sınıfları, evrensel bir temel sınıftan miras almaz. Bir üst sınıf belirtmeden tanımladığınız sınıflar, üzerine inşa edebileceğiniz temel sınıflar haline gelir.


Referans

https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Inheritance.html#//apple_ref/doc/uid/TP40014097-CH17-XID_251


-6

Bu normal. Swift'in tasarım hedeflerine bakın: Amaç, büyük programlama problemleri sınıflarını ortadan kaldırmaktır. Yöntemle dövüşmek muhtemelen Swift ile yapmak isteyeceğiniz şeylerden biri değil.


3
Metot sallama, çalışma zamanında kesişme modeline ulaşmanın bir yoludur. Bunun kullanımlarından biri, Aspect Oriented Programming ilkelerine göre kesişen endişeleri uygulamaktır. Apple'ın kendi bildirimleri, mülk gözlemcileri (yerleşikten hızlıya kadar), temel verilerin tümü iyi bir etki için döndürmeyi kullanır. . Hantal sözdizimine rağmen insanları Objective-C'ye hayran bırakan şeylerden biri de bu dinamizmdi, bu da kesişme modeli gerektiğinde zarif çözümler sunmayı kolaylaştırıyor. . Aslında Objc için resmi bir AOP çerçevesi yoktu, çünkü hammaddeler çok iyiydi.
Jasper Blues

Bunun şimdi böyle yapıldığı gerçeği, yarın böyle yapılacağı anlamına gelmez. Sizin de söylediğiniz gibi, mülk gözlemcileri, temsilciler ve benzerleri yerel olarak sağlanır veya sağlanabilir. Dil gelişecek ve hangi yönde gelişeceğini bilmiyoruz. Fonksiyonel programlama desteği açısından çok şey kazanmıştır . Ama bunu alışılmadık bir şekilde yapıyor, bu yüzden ne kadar eksik olduğu hakkında hiçbir fikrim yok. Yine de bildiğimiz kadarıyla, mutasyonu caydırmaya ve saf işlevsel programlamayı teşvik etmeye yöneliyor olabilirler. Ya kullanıcı arayüzünün geleceği reaktifse? Henüz bilmenin bir yolu yok.
Analog Dosya

1
Evet, ancak bunların tümü, iki yolla yapılabilen durdurmaya bağlıdır: derleme zamanı (C ++) veya çalışma zamanı (Ruby, Objective-C, Java (asm, cglib, ApsectJ, vb. Aracılığıyla)). Modern diller bunu çalışma zamanında yapma eğilimindedir. İnsanlar Objective-C'yi seviyorlardı çünkü eski bir kodlayıcı olmasına rağmen modern bir dil gibi davrandı. Dediğiniz gibi, dilde ne kadar çok pişirilirse o kadar iyidir (iyi yapılması şartıyla!). . ama şimdilik biz NSObject önümüzdeki birkaç yıl içinde günlük uygulamalar için standart bir uygulama haline uzanan umut yüzden objc / Vakfı tarafından sağlanan mirası içine kanca.
Jasper Blues
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.