Mesajlar ve yöntemler arasındaki farklar?


13

Amaç C'de diğer nesnelere mesaj gönderme kavramınız var ve bu da C # ve Java gibi dillerde çağrı yapma yöntemine çok benziyor.

Fakat ince farklar tam olarak nedir? Kodumu düşünürken mesajlaşmayı nasıl düşünmeliyim?

Not: Burada biraz arka plan, Objective C ile ilgili bazı kavramları anlamaya çalışan bir C # / Java geliştiricisiyim.


2
Hepsi farklı diller olduğundan, farklılıklar ince değildir. Bunlar farklı diller. "kodumu düşünürken"? Hangi kod? Java veya C # hakkında düşünürken, mesajları düşünmezsiniz. Yöntemleri düşünüyorsunuz. İlişkisiz kavramlara sahip ilişkisiz dillerin "ince" farklılıklara nasıl sahip olabileceğini açıklığa kavuşturabilir misiniz?
S.Lott

1
Lütfen size stackoverflow.com at soru sorun
Amir Rezaei

1
Bu soru gerçekten StackOverflow'da olmalı mı? Bu kavramları programlama hakkında bir soru var bazı kod hakkında bir sorun değil. Belki yanılıyorum, bilmiyorum - sınırlar bulanıklaşıyor ...
Vidar

1
@Vidar, soru öznel değil. Bir ders kitabı tanımı arıyorsunuz. Programcılar daha çok fikir, deneyim ve öznel sorular içindir.
Stephen Furlani

1
Tamam - moderatörün bu soruyu StackOverflow'a taşımasını sağlamanın bir yolu var mı?
Vidar

Yanıtlar:


10

Mesaj, bir seçicinin adı ve bu seçicinin parametreleridir.

Seçici bir semboldür.

Yöntem, sınıftaki bir seçici tarafından tanımlanan bir kod parçasıdır.

Başka bir deyişle, [foo bar: baz]" @selector(bar:)parametresi ile çağrılan iletiyi baznesneye gönder" der foo. Bu iletiyi birçok farklı nesneye gönderebilirsiniz.

Buna karşılık, yöntem bar: bir için Foogibi görünebilir

-(int)bar:(int)n {
  return n + 1;
}

ama FooTwogörünüşe göre

-(int)bar:(int)n {
  return n + 2;
}

(Umarım sentaks hakkım vardır; Objective-C'ye en son dokunduğumdan beri bir süre geçti.)

İletiyi gönderdiğinizde, Objective-C çekirdeği iletiyi foo anlayıp anlamayacağına karar veren . Buna, seçicinin belirlediği bir yöntemi bulup bulamayacağına göre karar verir.

Aynı ada sahip iki yöntem ve bir mesaj.

Bir nesnenin belirli bir mesajı (veya mesaj kümesini) işlenmek üzere başka bir nesneye iletmesi de mümkündür. Bu durumda, bu proxy nesnesine o iletiyle eşleşecek yöntemi olmayan bir ileti gönderirsiniz ve proxy iletiyi kaydırılan nesnesine iletir.


yani ... bir mesaj bir dispinterface (a.invoke selector, args) çağırdığınızda ve bir yöntem bir arabirim (a.methodName) çağırdığınızda? Java, JavaScript, tüm dinamik dillerin iletileri olmaz mı, çünkü her şey doğrudan atlamalar yerine çift arayüz üzerinden gerçekleşir ve vtable atlamalara kaydırılır)?
Dmitry

4

Tamamen teorik bir bakış açısından, ikisi arasında hiçbir fark yoktur - ikisinin tamamen eşdeğer olduğunu ve ya tamamen diğeri açısından uygulanabileceğini gösteren bir takım resmi kanıtlar vardır.

Biraz daha az teorik bir bakış açısından, olası bir fark vardır: tipik bir uygulamada, sanal fonksiyon tablosu statik olarak tahsis edilir ve her vtable'ın içeriği derleme zamanında sabitlenir. Mesaj arama, aksine, tipik olarak dinamik olan bir çeşit harita benzeri nesne ile yapılır, yani çalışma zamanında değiştirebilirsiniz. Bu, varolan bir sınıftaki iletiye yeni bir yanıt eklemeyi nispeten kolaylaştırır. Ne yazık ki, çoğu durumda bu çoğunlukla teorik olarak kalmaktadır. Birincisi, temelde kendini değiştiren kodla uğraşıyorsunuz, çoğu insanın oldukça kötü bir fikir olduğuna uzun zamandırzaman önce. İkincisi, çok anlamlı hale getirmek için, desteklediğiniz yeni mesaja cevap vermek için mevcut sınıfa yeni bir kod derlemeniz gerekir. Bu olmadan, elde ettiğiniz tek şey, mevcut bir yöntem için dinamik olarak yeni bir ad ekleme yeteneğidir.

Önceki paragrafın sonunda ima edildiği gibi, gerçekten pratik bir bakış açısından, ikisi arasında çok az fark vardır. Geç bağlanmayı desteklemenin iki (çok az) farklı yolu var. Mesaj tabanlı arama genellikle biraz daha yavaş olmasına rağmen, farkın gerçekten anlamlı olması oldukça sıra dışı olacaktır. En pratik amaçlar için, aynı şeyi başarmanın sadece iki farklı yoludur.


3
İspatları gösteren referanslarınız var mı? Bir göz atmak istiyorum. Java'nın yöntem çağırma ve Smalltalk'ın mesaj gönderme arasında, sadece geç bağlama nedeniyle değil, aynı zamanda gönderen ve alıcının ayrılması nedeniyle de büyük bir fark vardır: bir mesaj alıcısının mesajı işleyip işlemediğini söyleyemezsiniz veya iletiyi iletir örneğin.
Frank Shearar

@FrankShearar: Üzgünüm ama hayır. Gördüğüm kanıtlar basıldı ve uzun zaman önce OOP ve uygulama yöntemleri, bu tür şeylerin kanıtlarının akademisyenler için ilginç olacağı kadar yeni olduğunda.
Jerry Coffin

1

Objective-C'de mesajlar geç bağlıdır. Yani çalışma zamanında çözülürler. C #, bir nesnenin geç bağlı olduğunu bildiren Dynamic anahtar sözcüğü aracılığıyla benzer bir yapıyı destekler.


0

Genellikle yöntem çağrıları derleme zamanında çözümlenir (Java'da yansıma kullanmadığınız sürece), Amaç C'deki iletiler çalışma zamanında gönderilir.


2
Metod çağrıları çözüldüğünde derleme zamanı geliyorsa, OOP kullanmıyorsunuz struct, ilk parametre olarak aşırı yüklenmiş fonksiyonlar için sözdizimsel şeker kullanıyorsunuz . Geç bağlanma polimorfizmin ve dolayısıyla OOP'nin önemli bir parçasıdır.

2
Evet. Ancak yine de yalnızca bir yöntem çağrısını derleme zamanında iyi bilinen bir şeye (Java'da) kodlayabilirsiniz. MyObject veya MyInterface için tanımlanmış bir foo () yöntemi yoksa MyObject.foo () öğesini çağırmak hata verir. ObjC size MyObject nesnesine 'foo' mesajı göndermenize izin verir - ve MyObject 'foo' yoksa, bu çalışma zamanında bombalanır.
Heiko Rupp

Amaç C'nin derlenmiş bir dil olduğunu mu düşündüm?
Vidar

1
Bu, erken / geç bağlama için dinamik değildir (dinamik yazım ile yapısal yazım karşılaştırması - örneğin, yöntem çağrıları derleme zamanında kontrol edilir , ancak zorunlu olarak gönderilmez ). @Vidar: Öyle, ama dinamik özellikler için sihir katıyor. Ayrıca Python'u da derleyebilirsiniz.

@Vidar: Bu derlenmiş ve yorumlanmış bir konu değil, durağan ve dinamik bir konu. Java gibi statik OOP dillerinde derleyici, bir sınıfın derleme aşamasında bir yöntem tanımladığından emin olmak için denetler. Objective-C gibi dinamik olarak yazılan bir dilde, mesajlar çalışma zamanında iletilir.
mipadi

-1

İletiler çekirdek tarafından veya dilin kendisi tarafından işlenir (örneğin, ObjC için, bunu yapan çok küçük bir montaj kodu vardır).

Örneğin linux çekirdeğinde, mesajlar sistem çağrıları / işlevi ile yapılır: unix sistem programlaması hakkında arama yaparsanız bunlar hakkında bilgi bulabilirsiniz.

Bir yöntem çağrısı ile bir mesaj arasındaki temel fark şudur:

  • bir yöntem çağrısı yalnızca kodunuzda gerçekleşir: ASM'de iletilen bağımsız değişkenlerin PUSH'si tarafından çevrilir.

  • çekirdek mesajı çoğunlukla çekirdeğe gönderilen ve izlenen ve belirli işlemlere geri gönderilen bir şeydir. Onları borular için yanıltabilirim, ama her neyse: zaten aynı anda birkaç programı çalıştırmanıza ve aynı anda iletişim kurmanıza izin veren bir mekanizma olduğunu bilin. Tabii ki, bunun windows veya diğer işletim sistemlerinde aynı şekilde çalışacağını ummayın.


Programlama dilleri için geçerli olduğu için bu "mesaj iletme" değildir.
mipadi
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.