Nesne özelliklerine bir nesne yöntemi içinden nasıl erişirsiniz? [kapalı]


96

Alıcı / ayarlayıcı yöntemi olmayan bir nesne yöntemi içinden bir nesnenin özelliklerine erişmenin "saf" veya "doğru" yolu nedir?

Nesnenin dışından bir alıcı / ayarlayıcı kullanmanız gerektiğini biliyorum, ancak içeriden yaparsınız:

Java:

String property = this.property;

PHP:

$property = $this->property;

yoksa yapar mısın:

Java:

String property = this.getProperty();

PHP:

$property = $this->getProperty();

Java'm biraz bozuksa beni affet, Java'yı programladığımdan bu yana bir yıl geçti ...

DÜZENLE:

Görünüşe göre insanlar sadece özel veya korumalı değişkenler / özellikler hakkında konuştuğumu varsayıyor. OO'yu öğrendiğimde, herkese açık olsa bile her bir mülk için alıcılar / ayarlayıcılar kullanmam öğretildi (ve aslında hiçbir değişkeni / mülkü halka açık hale getirmemem söylendi). Yani, en başından beri yanlış bir varsayımdan yola çıkmış olabilirim. Görünüşe göre bu soruyu yanıtlayan insanlar, belki de kamusal mülklere sahip olmanız gerektiğini ve bunların alıcılara ve ayarlayıcılara ihtiyaç duymadığını söylüyorlar, bu bana öğretilenlere ve bahsettiğim şeye aykırıdır, ancak belki de şu şekilde tartışılması gerekir. iyi. Bu muhtemelen farklı bir soru için iyi bir konu ...

Yanıtlar:


62

Bunun dini savaş potansiyeli var, ama bana öyle geliyor ki, alıcı / ayarlayıcı kullanıyorsanız, onu dahili olarak da kullanmalısınız - her ikisini de kullanmak, yolun ilerleyen kısımlarında bakım sorunlarına yol açacaktır (örneğin, biri, ihtiyacı olan bir ayarlayıcıya kod ekler. bu özellik her ayarlandığında ve özellik, çağrılan ayarlayıcı olmadan dahili olarak ayarlanır).


bir ayarlayıcıda özelliğin değerini Java'da yanlış kullanım örneği olarak ayarlamak dışında başka bir şey yapmıyor.
euphoria83

1
@ euphoria83 Belki, ama bu olmasını engellemez.
Greg Hurlman

Orijinal cevaba katılıyorum. Ancak, sınıfın veya nesnenin içinde özel bir şey ayarlıyor veya alıyorsanız, alıcı / ayarlayıcının kodunuzun başarısız olmasına neden olacak şekilde döngüsel veya fazlalık olmadığından emin olmanız gerektiğini unutmayın. Alıcı / ayarlayıcıyı kullanamıyorsanız, doğrudan erişin. (Ör. Alıcınız / ayarlayıcınız, verileri değiştirmek için ikincil (özel / korumalı) bir yönteme erişir.)
Rick Mac Gillis

43

Şahsen, tutarlı kalmanın önemli olduğunu hissediyorum. Alıcılarınız ve ayarlayıcılarınız varsa, onları kullanın. Bir alana doğrudan erişeceğim tek zaman erişimcinin çok fazla ek yükünün olduğu zamandır. Gereksiz yere kodunuzu şişiriyormuşsunuz gibi gelebilir, ancak kesinlikle gelecekte çok fazla baş ağrısından kurtulabilir. Klasik örnek:

Daha sonra, bu alanın çalışma şeklini değiştirmek isteyebilirsiniz. Belki anında hesaplanmalı veya belki de destek mağazası için farklı bir tür kullanmak istersiniz. Özelliklere doğrudan erişiyorsanız, böyle bir değişiklik çok fazla kodu tek bir kabarıklıkta kırabilir.


26

Duyguların ne kadar oybirliğiyle olduğuna gettersve ayarlayıcıların iyi ve iyi olduğuna oldukça şaşırdım . Allen Holub'un " Getters And Setters Are Evil " adlı yangın çıkarıcı makalesini öneriyorum . Verilmiş, başlık şok değeri içindir, ancak yazar geçerli puanlar veriyor.

Esasen, varsa gettersve settersher özel alan için, herkese açık olarak iyi olarak bu alanları yapıyoruz. Bunu çağıran her sınıfa dalga etkisi olmadan özel bir alanın türünü değiştirmek için çok zorlanacaksınız getter.

Dahası, katı bir OO bakış açısından, nesneler (umarız) tek sorumluluklarına karşılık gelen mesajlara (yöntemlere) yanıt vermelidir. Büyük çoğunluğu gettersve settersonların kurucu nesneler için anlam ifade etmeyen; Pen.dispenseInkOnto(Surface)bana daha mantıklı geliyor Pen.getColor().

Getiriciler ve ayarlayıcılar ayrıca sınıfın kullanıcılarını nesneden bazı verileri istemeye, bir hesaplama yapmaya ve ardından nesnede daha iyi bilinen yöntemsel programlama olarak bilinen başka bir değer ayarlamaya teşvik eder. İlk etapta, basitçe nesneye yapacaklarınızı yapmasını söylemeniz daha iyi olacaktır; Bilgi Uzmanı deyimi olarak da bilinir .

Bununla birlikte, alıcılar ve ayarlayıcılar, katmanların sınırlarında gerekli kötülüklerdir - UI, ısrar vb. C ++ 'ın friend anahtar sözcüğü, Java'nın paket korumalı erişimi, .NET'in dahili erişimi ve Friend Class Pattern gibi bir sınıfın dahili öğelerine kısıtlı erişim , görünürlüğünü gettersve ayarlayıcıları yalnızca bunlara ihtiyacı olanlara indirmenize yardımcı olabilir .


19

Mülkün nasıl kullanıldığına bağlıdır. Örneğin, name özelliğine sahip bir öğrenci nesneniz olduğunu varsayalım. Zaten alınmamışsa, adı veritabanından çekmek için Get yönteminizi kullanabilirsiniz. Bu şekilde, veritabanına yapılan gereksiz çağrıları azaltırsınız.

Şimdi, nesnenizde adın kaç kez çağrıldığını sayan özel bir tam sayı sayacınız olduğunu varsayalım. Geçersiz bir sayım oluşturacağından, nesnenin içinden Get yöntemini kullanmak istemeyebilirsiniz.


Öğrenci nesnesi bir işletme / etki alanı nesnesiyse, artık altyapı ayrıntılarını karıştırıyorsunuzdur. İdeal olarak, bir iş / etki alanı nesneleri yalnızca iş / etki alanı mantığıyla ilgilenmelidir.
moffdub

Alıcıya şöyle bir tür boole eklerseniz: PHP: public function getName ($ outsideCall = true) {if ($ outsideCall) {$ this-> incrementNameCalled (); } $ this-> name döndür; } ve sonra Nesnenin içinden, eğer adı al'ı çağırdıysanız, artmasını engelleyebilirsiniz: PHP: $ isim = $ this-> getName (false); Burada denize mi düşüyorum?
cmcculloh

14

PHP bunun üstesinden gelmek için sihirli yöntemler de dahil olmak üzere sayısız yol sunar __getve __setben açık alıcıları ve ayarlayıcıları tercih ederim. İşte nedeni:

  1. Doğrulama ayarlayıcılara (ve bu konuda alıcılara) yerleştirilebilir
  2. Intellisense, açık yöntemlerle çalışır
  3. Bir özelliğin salt okunur mu, salt okunur mu yoksa okunur-yazılır mı olduğu sorusu yok
  4. Sanal özelliklerin alınması (yani hesaplanan değerler) normal özelliklerle aynı görünür
  5. Asla hiçbir yerde tanımlanmayan ve daha sonra belgelenmemiş olan bir nesne özelliğini kolayca ayarlayabilirsiniz.

13

Burada denize mi düşüyorum?

Belki;)

Diğer bir yaklaşım, alma işlemini (önbelleğe alma / db / vb.) Yapmak için özel / korumalı bir yöntem ve bunun için sayımı artıran genel bir sarmalayıcı kullanmak olabilir:

PHP:

public function getName() {
    $this->incrementNameCalled();
    return $this->_getName();
}

protected function _getName() {
    return $this->name;
}

ve sonra nesnenin içinden:

PHP:

$name = $this->_getName();

Bu şekilde, bu ilk argümanı başka bir şey için kullanmaya devam edebilirsiniz (önbelleğe alınmış verilerin burada kullanılıp kullanılmayacağına dair bir işaret göndermek gibi).


12

Buradaki noktayı kaçırıyor olmalıyım, o nesnenin bir özelliğine erişmek için neden bir nesnenin içinde bir alıcı kullanasınız?

Bunu sonuca götürürsek, alıcı bir alıcı çağırmalı ve alıcı çağırmalıdır.

Bu nedenle, bir nesne yönteminin içinden bir özelliğe doğrudan erişmenin, özellikle o nesnede başka bir yöntemi çağırmanın (ki bu, özelliğe doğrudan erişip sonra onu geri getirecek) sadece anlamsız, savurgan bir egzersizdir (veya soruyu yanlış anladım mı? ).


Ben yorumun zorunda aynı ihtiyacı sürüldü ... Artı kapatılmamış cevap verilmiştir;)
Yumurta Vans

8

Pürist OO yöntemi, her ikisinden de kaçınmak ve Tell Don't Sor yaklaşımını kullanarak Demeter Yasasını takip etmektir .

İki sınıfı sıkı bir şekilde birleştiren nesnenin özelliğinin değerini almak yerine , nesneyi bir parametre olarak kullanın, örn.

  doSomethingWithProperty() {
     doSomethingWith( this.property ) ;
  }

Özelliğin yerel bir tür olduğu durumlarda, örneğin int, bir erişim yöntemi kullanın, onu programlama etki alanı yerine sorun etki alanı için adlandırın.

  doSomethingWithProperty( this.daysPerWeek() ) ;

Bunlar, kapsüllemeyi ve herhangi bir son koşulları veya bağımlı değişmezleri korumanıza izin verecektir. Ayarlayıcı yöntemini herhangi bir ön koşulu veya bağımlı değişmezleri korumak için de kullanabilirsiniz, ancak onları ayarlayıcıları adlandırma tuzağına düşmeyin, deyimi kullanırken adlandırma için Hollywood İlkesine geri dönün.


8

Nesne içinde bile erişimci yöntemlerini kullanmak daha iyidir. İşte hemen aklıma gelen noktalar:

  1. Nesne dışından yapılan erişimlerde tutarlılığı sağlamak amacıyla yapılmalıdır.

  2. Bazı durumlarda, bu erişimci yöntemleri yalnızca alana erişimden daha fazlasını yapıyor olabilir; bazı ek işlemler yapıyor olabilirler (bu nadirdir). Durum böyleyse, alana doğrudan erişim, bu ek işlemin eksik olduğu anlamına gelir ve bu işlem her zaman bu erişimler sırasında yapılacaksa programınız ters gidebilir.


8

"Purist" ile "çoğu kapsülleme" yi kastediyorsanız, o zaman genellikle tüm alanlarımı özel olarak bildiririm ve sonra sınıfın içinde "this.field" ı kullanırım. Alt sınıflar dahil diğer sınıflar için, alıcıları kullanarak örnek durumuna erişiyorum.


7

ayarlayıcıları / alıcıları kullanmanın kodumu okumayı kolaylaştırdığını buldum. Ayrıca, diğer sınıflar yöntemleri kullandığında verdiği denetimi de seviyorum ve eğer verileri değiştirirsem özelliğin saklayacağı.


7

Herkese açık veya korumalı mülklere sahip özel alanlar. Değerlere erişim, özellikler üzerinden geçmeli ve bir yöntemde birden fazla kullanılacaksa yerel bir değişkene kopyalanmalıdır. YALNIZCA uygulamanızın geri kalanını bu kadar ince ayarlamış, sarsılmış ve başka bir şekilde ilgili özelliklerinden geçerek değerlere erişmenin bir darboğaz haline geldiği yerlerde optimize ettiyseniz (Ve bu ASLA gerçekleşmeyecek, garanti ederim) başlamanız gerekir özellikler dışında herhangi bir şeyin arka değişkenlerine doğrudan dokunmasına izin vermeyi düşünmek.

.NET geliştiricileri bunu zorlamak için otomatik özellikleri kullanabilir, çünkü tasarım zamanında destek değişkenlerini bile göremezsiniz.



7

Yanlış olabilirim çünkü autodidact'ım, ancak Java sınıflarımdaki genel özellikleri ASLA kullanmam, bunlar her zaman özel veya korumalıdır, bu nedenle dış kodun alıcılar / ayarlayıcılar tarafından erişilmesi gerekir. Bakım / tadilat amaçları için daha iyidir. Ve sınıf içi kod için ... Alıcı yöntemi önemsiz ise, özelliği doğrudan kullanırım, ancak her zaman ayarlayıcı yöntemlerini kullanırım çünkü istersem yangın olaylarına kolayca kod ekleyebilirim.


7

Özelliği düzenlemezsem, get_property()başka bir nesnenin içindeki MySQLi nesnesi gibi özel bir durum olmadığı sürece genel bir yöntem kullanacağım , bu durumda özelliği genel yapacağım ve ona $obj->object_property.

Nesnenin içinde benim için her zaman $ this-> property.


5

Görünüşe göre C # 3.0 özelliklerinin varsayılan uygulamasıyla karar sizin için alınır; özelliği (muhtemelen özel) özellik ayarlayıcısını kullanarak ayarlamanız GEREKİR.

Şahsen, özel üyeyi, bunu yapmadığımda, nesnenin istenenden daha az bir duruma düşmesine neden olacaksa, örneğin başlatma sırasında veya önbelleğe alma / tembel yükleme söz konusu olduğunda kullanıyorum.


5

Cmcculloh'un cevabını beğendim ama en doğru olanı Greg Hurlman'ın cevabı gibi görünüyor . Alıcı / ayarlayıcıyı en baştan kullanmaya başladıysanız ve / veya onlarla çalışmaya alışkınsanız her zaman kullanın.

Bir kenara, ben şahsen alıcı / ayarlayıcı kullanmanın kodu okumayı ve daha sonra hata ayıklamayı kolaylaştırdığını görüyorum.


4

Bazı yorumlarda belirtildiği gibi: Bazen yapmalısın, bazen yapmamalısın. Özel değişkenlerin en güzel yanı, bir şeyi değiştirdiğinizde kullanıldıkları tüm yerleri görebilmenizdir. Alıcı / ayarlayıcınız ihtiyacınız olan bir şeyi yaparsa, onu kullanın. Önemli değilse sen karar ver.

Tersi bir durum da yapılabilir: Alıcı / ayarlayıcıyı kullanırsanız ve birileri alıcı / ayarlayıcıyı değiştirirse, alıcı ve ayarlayıcının bir şeyi bozup bozmadığını görmek için dahili olarak kullanıldığı tüm yerleri analiz etmeleri gerekir.

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.