Java'daki nesneler gibi yapılandırın


195

Nesneler gibi yapı oluşturmak tamamen Java yoluna karşı mı?

class SomeData1 {
    public int x;
    public int y;
}

Erişimcilerin ve mutasyonların daha çok Java gibi olduğu bir sınıf görebiliyorum.

class SomeData2 {
    int getX();
    void setX(int x);

    int getY();
    void setY(int y);

    private int x;
    private int y;
}

İlk örnekten gelen sınıf notasyon olarak uygundur.

// a function in a class
public int f(SomeData1 d) {
    return (3 * d.x) / d.y;
}

Bu o kadar uygun değil.

// a function in a class
public int f(SomeData2 d) {
    return (3 * d.getX()) / d.getY();
}

9
Herkese açık değiştirilebilir alanlar yerine, genel olarak değiştirilemeyen alanları veya paket olarak yerel değiştirilebilir alanları düşünün. Her ikisi de daha iyi IMHO olurdu.
Peter Lawrey

Unutmayın, alıcılar ve ayarlayıcılar çirkin / ayrıntılı olsa da, bu bir çeşit Java'nın kalbidir. Kısa ve öz bir dil. Öte yandan, ASLA bunlardan hiçbirini yazmamalısınız, çünkü IDE'niz sizin için budur. Dinamik bir dilde daha az yazmanız gerekir, ancak yazmanız gerekir (genellikle IDE'ler yardımcı olabilir).
Dan Rosenstark

İronik olarak, OO kapsülleme açısından güçlü yönlere sahip olsa da, bu CPU ve depolama açısından ücretli bir fiyat var. Çöp toplayıcı (neredeyse tamamen) nesne referanslarının ne zaman temizlenmesi gerektiği konusunda endişelenme gereğini ortadan kaldırır. Mevcut eğilim, C-benzeri yapıları yığın dışı kullanarak tam bir döngüye giriyor. Bu, önbellekleme tipi çözümler, süreçler arası iletişim, daha hızlı bellek yoğun işlemler, daha düşük GC o / h için mükemmeldir ve hatta veri kümeleriniz için daha düşük depolama o / saatinden yararlanabilir. Ne yaptığını biliyorsan, bu soruyu sormazdın ... o yüzden tekrar düşün!
user924272

@ user924272: Re "Şu anki eğilim, C-benzeri yapıları yığın halinde kullanarak tam döngüye giriyor". Java nasıl yapacaktı ??? IMHO, Java'nın yaşını gösterdiği bir alandır ...
ToolmakerSteve

@ToolmakerSteve -Bir daire görüyorum. Sadece ben değilim. Azul gibi şirketler duraklamayan çöp toplama konusunda sıcaklar. Java eskidir. Doğru. Bir zayıflığı fark eden ve inilti yerine bu konuda bir şeyler yapan mühendisler? Saygıyı hak ediyorlar! +10 benden Azul :-)
user924272

Yanıtlar:


62

Bu yaygın olarak tartışılan bir konudur. Nesnelerde ortak alanlar oluşturmanın dezavantajı, kendisine ayarlanan değerler üzerinde kontrolünüz olmamasıdır. Aynı kodu kullanan çok sayıda programcının bulunduğu grup projelerinde, yan etkilerden kaçınmak önemlidir. Ayrıca, bazen alan nesnesinin bir kopyasını döndürmek veya bir şekilde dönüştürmek vb. Daha iyidir. Bu tür yöntemleri testlerinizde taklit edebilirsiniz. Yeni bir sınıf oluşturursanız, olası tüm işlemleri göremeyebilirsiniz. Savunma programlama gibi - bir gün alıcılar ve ayarlayıcılar yardımcı olabilir ve bunları oluşturmak / kullanmak çok pahalı değildir. Bu yüzden bazen yararlı olurlar.

Uygulamada, çoğu alanın basit alıcıları ve ayarlayıcıları vardır. Olası bir çözüm şöyle görünecektir:

public property String foo;   
a->Foo = b->Foo;

Güncelleme: Özellik desteğinin Java 7'de veya belki de eklenmesi pek olası değildir. Groovy, Scala, vb. Gibi diğer JVM dilleri bu özelliği desteklemektedir. - Alex Miller


28
Bu çok kötü, C # tarzı özellikleri seviyorum (bu sizin hakkında konuştuğunuz gibi görünüyor)
Jon Onstott

2
Bu yüzden aşırı yükleme kullanın ... private int _x; genel boşluk x (int değer) {_x = değer; } public int x () {dönüş _x; }
Gordon

12
Bence =kodu daha temiz kılan kullanmayı tercih ediyorum .
Svish

6
@ T-Bull: Çünkü xiki farklı şey olan iki siniz olabilir, bu iyi bir fikir değildir. IMHO, bu kötü bir öneri, çünkü insan okuyucuların kafa karışıklığına yol açabilir. Temel ilke: Bir okuyucuyu iki kere yapmayın; söylediklerinizi açıklığa kavuşturun - Farklı varlıklar için farklı adlar kullanın. Fark sadece bir alt çizginin önüne geçmek olsa bile. Varlıkları ayırt etmek için etraftaki noktalama işaretlerine güvenmeyin.
ToolmakerSteve

2
@ToolmakerSteve: Kodlama dogmasını savunmak söz konusu olduğunda (kodlama stilinin aksine) "karışıklığa yol açabilir" en yaygın ve en zayıf argüman. Her zaman en basit şeylerle karıştırılabilecek biri vardır. Birisini her zaman uyanık kaldıktan ve yarım hafta veya bir süre kodlamadan sonra yanıltıcı kodlama stilini suçladıktan sonra bir hata yaptığını şikayet eden birini bulacaksınız. Buna izin vermem. Bu stil geçerli, açık ve ad alanını temiz tutar. Ayrıca, burada farklı varlıklar yok, etrafında / bir / varlık ve çevresinde bazı kaynak kodu var.
T-Bull

290

Birçok Java çalışanı, Java destekli "yapı" destekliyorsa (davranış yoksa), sınıf temelde bir "Yapı" olduğunda genel örnek değişkeninin kullanılmasının oldukça uygun olduğunu söyleyen Sun Java Kodlama Yönergeleri'ne aşina olmadığı anlaşılmaktadır.

İnsanlar, sanki Java'nın kalbi gibi, alıcıların ve ayarlayıcıların Java yolu olduğunu düşünürler. Bu öyle değil. Sun Java Kodlama Yönergeleri'ni izlerseniz, uygun durumlarda genel yönetim ortamı değişkenlerini kullanarak, aslında gereksiz alıcılar ve ayarlayıcılarla karıştırmaktan daha iyi kod yazıyorsunuz demektir.

1999'dan beri Java Kod Sözleşmeleri ve hala değişmedi.

10.1 Örnek ve Sınıf Değişkenlerine Erişim Sağlama

Herhangi bir örneği veya sınıf değişkenini iyi bir neden olmadan herkese açık hale getirmeyin. Çoğunlukla, örnek değişkenlerinin yöntem çağrılarının bir yan etkisi olarak açıkça ayarlanması veya sık sık alınması gerekmez.

Uygun halka açık değişkenlerin bir örneği, sınıfın temelde davranışsız bir veri yapısı olduğu durumdur. Başka bir deyişle, sınıf yerine bir yapı (Java destekli yapı destekliyorsa) kullanırsanız, sınıfın örnek değişkenlerini herkese açık hale getirmek uygun olur .

http://www.oracle.com/technetwork/java/javase/documentation/codeconventions-137265.html#177

http://en.wikipedia.org/wiki/Plain_old_data_structure

http://docs.oracle.com/javase/1.3/docs/guide/collections/designfaq.html#28


88
+1 Aslında yetkili bir kaynağa sahip olduğu için. Diğer her yanıt, insanlar gerçekler gibi düşüncelerini döndürüyor.
ArtOfWarfare

1
Get ve set yöntemlerini kullanarak özelliklere erişmenin endüstri standardı bir yolu olan Java Beans özelliği vardır ... genel bakış için bkz. En.wikipedia.org/wiki/JavaBeans .
user924272

4
@ user924272: Bu Java Beans spesifikasyonu "genel örnek değişkenleri" nin ne zaman kullanılmasının uygun olduğunu tartışan bu cevapla nasıl alakalı? Spesifikasyon, örnek değişkenlerini otomatik olarak özelliklere dönüştürmek için standart bir yol olsaydı, ala C #, alakalı olabilir. Ama değil, değil mi? Bu tür bir eşleme yapmak için sadece kazan plakası alıcılarının ve oluşturulması gereken ayarlayıcıların adlarını belirtir.
ToolmakerSteve

@ToolmakerSteve. Bu bir java sorusu. Ayrıca, soru bir spesifikasyonun mevcut olduğu ortak bir problemden kaçınmaktadır. Eski okul perspektifinden bakıldığında, standart bir yol olduğunda alan mutasyonlarında hata ayıklamak çok daha kolaydır - bir ayarlayıcıya bir kesme noktası ayarlayın. Bu muhtemelen modern hata ayıklayıcılarla modası geçmiş, ancak nesneleri doğrudan "delen" sınıflara kaşlarını çatmak zorunda kaldım ... bu daha küçük uygulamalar için uygun olsa da, daha büyük uygulamalar ve büyük organizasyonlar için gerçek bir baş ağrısıdır
user924272

223

Sağduyuyu gerçekten kullanın. Gibi bir şey varsa:

public class ScreenCoord2D{
    public int x;
    public int y;
}

Sonra onları alıcılara ve pasörlere sarmanın pek bir anlamı yok. Asla x, y koordinatlarını başka bir şekilde tam piksel olarak depolamayacaksınız. Harfler ve ayarlayıcılar sadece sizi yavaşlatır.

Öte yandan, ile:

public class BankAccount{
    public int balance;
}

İleride bir noktada bakiyenin hesaplanma şeklini değiştirmek isteyebilirsiniz. Bu gerçekten alıcıları ve ayarlayıcıları kullanmalıdır.

Neden iyi uygulama uyguladığınızı bilmek her zaman tercih edilir , böylece kuralları bükmenin ne zaman uygun olduğunu bilirsiniz.


3
Bu cevap razı ve bu kadar uzun alanlardır gibi kamu alanlarına sahip bir sınıf oluşturabileceği ileri söylemek kalın birbirinden bağımsız. yani bir alan diğerine bağımlı değildir. Bu, birçok durumda, bir fonksiyondan çoklu dönüş değerleri veya polar ko-odinatlar için oldukça yararlı olabilir. {açı, uzunluk} birlikte giderler, ancak içsel olarak birbirine bağımlı değildirler.
Spacen Jasset

@SpacenJasset: FYI, örneklerinizin (çoklu dönüş değerleri; kutupsal koordinatlar) genel alanların alıcı / ayarlayıcılara karşı kullanılıp kullanılmayacağına dair bir etkisi olmadığını görmüyorum. Birden fazla dönüş değeri durumunda, karşı üretken bile olabilir, çünkü tartışmalı olarak, arayan kişi sadece kamu alıcıları ve özel pasifler (değişmez) lehine savunulan döndürülen değerleri ALMALIDIR. Bu, bir (x, y) nesnesinden kutup koordinatlarını döndürmek için de geçerli olabilir - kutupsal koordinatın ayrı bileşenlerindeki değişiklikler (x, y) 'ye dönüştürüldüğünden TOPLAM matematik hatalarını göz önünde bulundurun.
ToolmakerSteve

@SpacenJasset: Ama senin prensibine katılıyorum.
ToolmakerSteve

1
Geçerli bir noktanız var, ancak pikselin pencerenin içinde olduğundan emin olmanın kötü bir örnek olduğunu hissediyorum (sadece bir örnek) , birinin yapabileceği bir şeydir ve ayrıca birisinin pikseli ayarlamasına izin (-5, -5)vermemek iyi bir fikir. :-)
Horsey

50

Değiştirilebilirlik sorunlarını gidermek için x ve y'yi son olarak bildirebilirsiniz. Örneğin:

class Data {
  public final int x;
  public final int y;
  public Data( int x, int y){
    this.x = x;
    this.y = y;
  }
}

Bu alanlara yazmaya çalışan arama kodu, "x alanı son olarak bildirildi; atanamaz" derleme zamanı hatası alır.

Müşteri kodu daha sonra yayınınızda tanımladığınız 'kısa el' kolaylığına sahip olabilir

public class DataTest {
    public DataTest() {
        Data data1 = new Data(1, 5);
        Data data2 = new Data(2, 4);
        System.out.println(f(data1));
        System.out.println(f(data2));
    }

    public int f(Data d) {
        return (3 * d.x) / d.y;
    }

    public static void main(String[] args) {
        DataTest dataTest = new DataTest();
    }
}

3
Teşekkürler - yararlı ve özlü bir cevap. Değiştirilebilirlik istemediğinde alan sözdiziminin nasıl faydalanacağını gösterir.
ToolmakerSteve

@ToolmakerSteve - geribildirim için teşekkürler - çok takdir etmek.
Brian

Bir final sınıfının son örneklerini yapı "örnekleri" olarak son alanlarla kullanmaya çalıştım, ancak caseböyle bir örnek alanına atıfta bulunan bir ifadede anladım Case expressions must be constant expressions. bunun yolu nedir? buradaki deyimsel kavram nedir?
n611x007

1
son alanlar, sınıf ilk kullanıldığında başlatılacağı için sabit olmayan nesnelere hala başvurudur. Derleyici nesne başvurularının "değerini" bilemez. Derleme yapılırken sabitler bilinmelidir.
Johan Tidén

1
+1 Gerçekten önemli bir cevap. Bence değişmez sınıfların faydası göz ardı edilemez. "Ateşle ve unut" semantikleri, özellikle senkronizasyon olmadan, evreler arasında keyfi olarak paylaşılabildikleri çok iş parçacıklı ortamlarda kod hakkında akıl yürütmeyi daha basit hale getirir.
TheOperator

11

publicAlanları kullanma

publicBir sınıfın iç davranışını gerçekten sarmak istediğinizde alanları kullanmayın . java.io.BufferedReaderÖrneğin ele alalım. Aşağıdaki alana sahiptir:

private boolean skipLF = false; // If the next character is a line feed, skip it

skipLFtüm okuma yöntemlerinde okunur ve yazılır. Ayrı bir iş parçacığında çalışan bir dış sınıf skipLF, okumanın ortasında durumunu kötü bir şekilde değiştirirse ne olur ? BufferedReaderkesinlikle haywire gidecek.

publicAlanları kullanma

Örneğin bu Pointsınıfı ele alalım:

class Point {
    private double x;
    private double y;

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }

    public double getX() {
        return this.x;
    }

    public double getY() {
        return this.y;
    }

    public void setX(double x) {
        this.x = x;
    }

    public void setY(double y) {
        this.y = y;
    }
}

Bu, iki nokta arasındaki mesafenin hesaplanmasını çok acı verici hale getirecektir.

Point a = new Point(5.0, 4.0);
Point b = new Point(4.0, 9.0);
double distance = Math.sqrt(Math.pow(b.getX() - a.getX(), 2) + Math.pow(b.getY() - a.getY(), 2));

Sınıfın düz alıcılar ve ayarlayıcılar dışında herhangi bir davranışı yoktur. Sınıf yalnızca bir veri yapısını temsil ettiğinde ve hiç davranmadığında ve hiçbir zaman davranışa sahip olmadığında ortak alanları kullanmak kabul edilebilir (ince alıcılar ve ayarlayıcılar burada davranış olarak kabul edilmez ). Bu şekilde daha iyi yazılabilir:

class Point {
    public double x;
    public double y;

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
}

Point a = new Point(5.0, 4.0);
Point b = new Point(4.0, 9.0);
double distance = Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2));

Temiz!

Ancak unutmayın: Sadece sınıfınız davranışlardan yoksun olmakla kalmamalı, aynı zamanda gelecekte de davranmak için hiçbir nedene sahip olmamalıdır .


(Bu cevap tam olarak budur . "Java Programlama Dili için Kod Kuralları: 10. Programlama Uygulamaları" nı belirtmek için :

Uygun halka açık değişkenlerin bir örneği, sınıfın temelde davranışsız bir veri yapısı olduğu durumdur. Başka bir deyişle, structsınıf yerine bir tane kullanırsanız (Java destekli ise)struct ) kullanırsanız, sınıfın örnek değişkenlerini herkese açık hale getirmek uygun olur.

Dolayısıyla resmi belgeler de bu uygulamayı kabul etmektedir.)


Ayrıca, yukarıdaki Pointsınıftaki üyelerin değişmez olması gerektiğinden eminseniz, finalbunu uygulamak için anahtar kelime ekleyebilirsiniz :

public final double x;
public final double y;

8

Bu arada, örnek olarak verdiğiniz yapı olarak Java temel sınıf kitaplığında zaten var java.awt.Point. Ortak alanlar olarak x ve y vardır, kendiniz kontrol edin .

Ne yaptığınızı biliyorsanız ve ekibinizdeki diğer kişiler bunu biliyorsa, o zaman herkese açık alanlara sahip olmak iyidir. Ancak buna güvenmemelisiniz çünkü nesneler kullanan geliştiricilerle ilgili hatalarda olduğu gibi yığın tahsis edilmiş yapılar gibi baş ağrısına neden olabilirler (java nesneleri her zaman yöntem olarak referans olarak gönderilir, kopya olarak değil).


+1 Bir sorundan iyi bahsediyoruz - sonucun hala bir C yapısı gibi DEĞİLDİR. Bununla birlikte, her zaman referans olarak olmak üzere java nesneleri hakkında ortaya koyduğunuz sorun, genel olarak yazılabilir bir alan (OP'nin sorusunun özüdür - hangi temsilin kullanılacağı) yerine bir ayarlayıcı oluşturularak iyileştirilmez. Aksine, NEITHER yapmaktan yana bir argüman. Bu, UYGUNLUK için bir argüman. Bu, bir public finalalan olarak, Brian'ın cevabında olduğu gibi veya bir kamu alıcısına sahip olabilir, ancak halka açık bir pasör olabilir. Yani, alan veya erişimci kullanıp kullanmadığı önemsizdir.
ToolmakerSteve

8

Re: aku, izb, John Topley ...

Değiştirilebilirlik sorunlarına dikkat edin ...

Alıcıları / belirleyicileri atlamak mantıklı görünebilir. Bazı durumlarda aslında iyi olabilir. Burada gösterilen önerilen modelle ilgili gerçek sorun değişebilirliktir.

Sorun nihai olmayan, ortak alanları içeren bir nesne başvurusu geçirdiğinizde. Bu referansa sahip her şey bu alanları değiştirmekte özgürdür. Artık o nesnenin durumu üzerinde herhangi bir kontrole sahip değilsiniz. (Dizeler değiştirilebilir olsaydı ne olacağını düşün.)

Bu nesne bir başkasının iç durumunun önemli bir parçası olduğunda kötüleşir, sadece içsel uygulamayı açtınız. Bunu önlemek için, nesnenin bir kopyası döndürülmelidir. Bu çalışır, ancak oluşturulan tonlarca tek kullanımlık kopyadan büyük GC basıncına neden olabilir.

Genel alanlarınız varsa, sınıfı salt okunur yapmayı düşünün. Alanları yapıcıya parametre olarak ekleyin ve alanları son olarak işaretleyin. Aksi takdirde, dahili durumu göstermediğinizden emin olun ve bir dönüş değeri için yeni örnekler oluşturmanız gerekiyorsa, bunun aşırı çağrılmayacağından emin olun.

Bakınız: Joshua Bloch tarafından " Etkili Java " - Madde # 13: Değiştirilemezlik.

Not: Ayrıca, bu günlerde tüm JVM'lerin mümkünse getMethod'u optimize ederek yalnızca tek bir alan okuma talimatıyla sonuçlanacağını unutmayın.


12
Alıcı / ayarlayıcı bu sorunu nasıl çözer? Hala bir referansınız var, işlemlerle herhangi bir senkronizasyonunuz yok. Harfler / ayarlayıcılar kendi başlarına koruma sağlamazlar.
he_the_great

1
Harfler ve ayarlayıcılar gerekirse senkronizasyon sağlayabilir. Ayrıca alıcıların ve belirleyicilerin belirttiklerinden daha fazlasını yapmasını bekliyorsunuz. Buna bakılmaksızın, senkronizasyon sorunu hâlâ yeniden ortaya çıkıyor.
user924272

7

Bunu birkaç projede, getters ve setters'ın semantik anlamsız bir hamle ile kodları karıştırdığı ve diğer dillerin, konvansiyona dayalı veri gizleme veya sorumlulukların bölümlenmesi (örn. Python) ile iyi olduğu görülüyor.

Diğerlerinin yukarıda belirttiği gibi, karşılaştığınız 2 sorun var ve bunlar gerçekten düzeltilemez:

  • Java dünyasındaki herhangi bir otomatik araç, alıcı / ayarlayıcı kuralına dayanır. Ditto, diğerleri tarafından belirtildiği gibi, jsp etiketleri, bahar konfigürasyonu, tutulma araçları vb. ... Araçlarınızın görmeyi beklediği şeylere karşı savaşmak, Google'ın standart olmayan başlatma yolunu bulmaya çalışan uzun oturumlar için bir reçetedir. bahar fasulye. Gerçekten sorun değmez.
  • Yüzlerce ortak değişkenle zarif bir şekilde kodlanmış uygulamanız olduğunda, muhtemelen yetersiz oldukları en az bir durum bulacaksınız - kesinlikle değişmezliğe ihtiyacınız var veya değişken ayarlandığında veya atmak istediğinizde bir olayı tetiklemeniz gerekiyor değişken bir değişiklik için bir istisna, çünkü bir nesne durumunu hoş olmayan bir şeye ayarlar. Daha sonra, uygulamanızdaki 1000 değişkenden 3'ü için bazı özel erişim formuna sahip olan, değişkenin doğrudan başvurulduğu her yerde özel bir yöntemle kodunuzu karıştırmak arasında kaçınılmaz seçeneklerle sıkışıp kalırsınız.

Ve bu tamamen bağımsız bir özel projede çalışmanın en iyi senaryosudur. Her şeyi halka açık bir kütüphaneye aktardığınızda, bu sorunlar daha da büyüyecektir.

Java çok ayrıntılı ve bu cazip bir şey. Yapma.


Kamusal alanların yoluna çıkma problemlerinin mükemmel tartışılması. C # 'dan Java'ya geri dönmek zorunda kaldığımda beni sinirlendiren Java'nın kesin bir eksikliği (burada Java'nın rahatsızlığından öğrenilen).
ToolmakerSteve

4

Java yolu OO yoluysa, evet, ortak alanlara sahip bir sınıf oluşturmak, bilgi gizleme çevresindeki bir nesnenin kendi iç durumunu yönetmesi gerektiğini söyleyen ilkeleri ihlal eder. (Yani sadece size jargon dökmek değilim, bilgi gizlemenin bir yararı, bir sınıfın iç işleyişinin bir arayüzün arkasında gizlenmiş olmasıdır - yapısal sınıfınızın alanlarından birini kaydetme mekanizmasını değiştirmek istediğinizi varsayalım, muhtemelen geri dönüp sınıfı kullanan tüm sınıfları değiştirmeniz gerekir ...)

Ayrıca, İfade Dili kullanılarak yazılmış bir JavaServer Sayfasında sınıfı kullanmaya karar verirseniz zarar verecek olan JavaBean adlandırma uyumlu sınıflar desteğinden de yararlanamazsınız.

JavaWorld makale alıcı ve ayarlayıcı yöntemleri Evil Neden ayrıca makale erişimci ve mutatör yöntemlerini uygulamak ne zaman kullanılmayacağı konusunda düşüncesinde ilginizi olabilir.

Küçük bir çözüm yazıyorsanız ve ilgili kod miktarını en aza indirmek istiyorsanız, Java yolu doğru yol olmayabilir - Sanırım her zaman size ve çözmeye çalıştığınız soruna bağlıdır.


1
"Getter ve Setter Yöntemleri Neden Kötülük" makalesine bağlantı için +1. Ancak, hem kamu alanları hem de kamu alıcıları / belirleyicilerinin ECHALLY Java yolu DEĞİL olduğuna dikkat çekerseniz, cevabınız daha açık olurdu: Bu makalede açıklandığı gibi - mümkünse de yapmayın. Bunun yerine, istemcilere örneğin iç temsilini yansıtmak yerine yapmaları gerekenlerle ilgili yöntemler sağlayın. ANCAK, bu geliştirici.g, izb ve Brian tarafından daha iyi cevaplanan sorulan soruya (basit, "yapı" durumu için kullanılacak) gerçekten değinmez.
ToolmakerSteve

3

Yazarın nesneler yerine yapı (veya veri servisleri) olduğunu bilmesi koşuluyla, bu tür kodlarda yanlış bir şey yoktur . Birçok Java geliştiricisi, iyi biçimlendirilmiş bir nesne (sadece java.lang.Object alt sınıfı değil, belirli bir etki alanındaki gerçek bir nesne) ve bir ananas arasındaki farkı söyleyemez . Ergo, nesnelere ve viceversa'ya ihtiyaç duyduklarında yapılar yazıyorlar.


ananas beni güldürüyor :)
Guillaume

Ancak, bu cevap bu farkın ne olduğu hakkında hiçbir şey söylemiyor. Vasıfsız geliştiriciler üzerinde bezeme yapmak, bu geliştiricilerin ne zaman yapı oluşturacaklarını ve ne zaman sınıf oluşturacaklarını bilmelerine yardımcı olmaz.
ToolmakerSteve

Fark hakkında hiçbir şey söylemez çünkü yazar farkın farkındadır (yapısal bir varlığın ne olduğunu bilir). Yazar, yapıların OO dilinde uygun olup olmadığını soruyor ve evet diyorum (sorunlu etki alanına bağlı olarak.) Soru, bir nesneyi gerçek bir etki alanı nesnesi yapan şeyle ilgiliyse, argüman.
luis.espinal

Ayrıca, farkı bilmemesi gereken vasıfsız geliştiricinin tek türü hala okulda olanıdır. Bu, bağlantılı bir liste ile bir karma tablo arasındaki farkı bilmek gibi son derece temeldir. Bir kişi gerçek bir nesnenin ne olduğunu bilmeden 4 yıllık bir yazılım derecesi ile mezun olursa, o kişi bu kariyer için kesilmez veya okula geri dönüp geri ödeme talep etmelidir. Ciddiyim.
luis.espinal

Ama şikayetinizi tatmin etmek için bir cevap vereceğim (orijinal soru ile ilgisi olmayan ve kendi konusunu hak eden). Nesnelerin davranışı ve kapsülleme durumu vardır. Yapılar yok. Nesneler durum makineleridir. Yapılar sadece verileri toplamak içindir. İnsanlar daha ayrıntılı bir cevap isterse, kalplerimizin içeriğine bu konuyu ayrıntılı olarak açıklayabileceğimiz yeni bir soru yaratmakta özgürdürler.
luis.espinal

2

Ortak alan erişimini kullanmayla ilgili sorun, fabrika yöntemi yerine yenisini kullanmakla aynı sorundur - daha sonra fikrinizi değiştirirseniz, mevcut tüm arayanlar bozulur. Bu nedenle, API evrim bakış açısından, mermiyi ısırmak ve alıcıları / ayarlayıcıları kullanmak genellikle iyi bir fikirdir.

Diğer yoldan gittiğim yerlerden biri, sınıfa, örneğin bir iç veri yapısı olarak kullanılan bir iç statik sınıfta erişimi güçlü bir şekilde denetlemenizdir. Bu durumda, saha erişimini kullanmak çok daha açık olabilir.

Bu arada, e-bartek'in iddiasında, Java 7'de özellik desteğinin eklenmesi pek olası değildir.


1
Bu doğrudur, ancak Java kullanıyorsanız bu bir endişe kaynağı değildir, çünkü tek bir tıklamayla tüm kod tabanını yeniden düzenleyebilirsiniz (Eclipse, Netbeans, muhtemelen VIM ve Emacs). Groovy gibi dinamik arkadaşlarından birini seçtiyseniz, basit bir kapsülleme bile saatlerce veya günlerce sabitlemenizi sağlayabilir. Neyse ki, sizi ne kadar çok kod düzeltmeniz gerektiğine dair bilgilendirecek test durumlarınız olacaktır.
Dan Rosenstark

2
Elbette tüm kullanıcıların kod tabanınızda olduğunu varsayarsınız, ancak elbette, bu genellikle doğru değildir. Çoğu zaman, teknik olmayan çeşitli nedenlerle kendi kod tabanınızda olabilecek kodu değiştirmek bile mümkün değildir.
Alex Miller

2

Kodumu basitleştirmek için özel iç sınıflar oluştururken bu kalıbı sık sık kullanıyorum, ancak bu tür nesneleri ortak bir API'de göstermenizi önermem. Genel olarak, genel API'nizdeki nesneleri ne kadar sık ​​değiştirilemez hale getirirseniz, 'yapı benzeri' nesnenizi değiştirilemez bir şekilde oluşturmak mümkün değildir.

Bir kenara, bu nesneyi özel bir iç sınıf olarak yazıyor olsam bile, yine de nesneyi başlatmak için kodu basitleştirmek için bir yapıcı sağlardım. Bir yapacağınız zaman kullanılabilir bir nesne elde etmek için 3 satır kod olması sadece dağınık.


2

Çok eski bir soru ama kısa bir katkı daha yapmama izin verin. Java 8 lambda ifadeleri ve yöntem referanslarını tanıttı. Lambda ifadeleri basit yöntem referansları olabilir ve "gerçek" bir cisim ilan etmeyebilir. Ancak bir alanı yöntem başvurusuna "dönüştüremezsiniz". Böylece

stream.mapToInt(SomeData1::x)

yasal değil, ama

stream.mapToInt(SomeData2::getX)

dır-dir.


Bu durumda kullanabilirsiniz data -> data.x, ki bu hala makul
James Kraus

1

Bunun her zaman basit bir yapı olacağını ve asla ona davranış eklemek istemeyeceğinizin zararını görmüyorum.


1

Bu, Java dili değil, Nesne Tabanlı Tasarım ile ilgili bir sorudur. Sınıf içindeki veri türlerini gizlemek ve yalnızca sınıf API'sinin parçası olan yöntemleri göstermek genellikle iyi bir uygulamadır. Dahili veri türlerini ortaya çıkarırsanız, bunları gelecekte asla değiştiremezsiniz. Onları gizlerseniz, kullanıcıya karşı tek yükümlülüğünüz yöntemin dönüş ve bağımsız değişken türleridir.


1

Burada 5 farklı kişinin Adını ve Yaşını girmek için bir program oluşturuyorum ve seçim sıralaması yapıyorum (yaş olarak). Tüm işlemi gerçekleştirmek için bir yapı (C programlama dili gibi) görevi gören bir sınıf ve bir ana sınıf kullandım. Aşağıda kodu veriyorum ...

import java.io.*;

class NameList {
    String name;
    int age;
}

class StructNameAge {
    public static void main(String [] args) throws IOException {

        NameList nl[]=new NameList[5]; // Create new radix of the structure NameList into 'nl' object
        NameList temp=new NameList(); // Create a temporary object of the structure

        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

        /* Enter data into each radix of 'nl' object */

        for(int i=0; i<5; i++) {
            nl[i]=new NameList(); // Assign the structure into each radix

            System.out.print("Name: ");
            nl[i].name=br.readLine();

            System.out.print("Age: ");
            nl[i].age=Integer.parseInt(br.readLine());

            System.out.println();
        }

        /* Perform the sort (Selection Sort Method) */

        for(int i=0; i<4; i++) {
            for(int j=i+1; j<5; j++) {
                if(nl[i].age>nl[j].age) {
                    temp=nl[i];
                    nl[i]=nl[j];
                    nl[j]=temp;
                }
            }
        }

        /* Print each radix stored in 'nl' object */

        for(int i=0; i<5; i++)
            System.out.println(nl[i].name+" ("+nl[i].age+")");
    }
}

Yukarıdaki kod Hatasız ve Test Edilmiştir ... Sadece kopyalayıp IDE'nize yapıştırın ve ... Biliyor musunuz ve ne ??? :)


0

Genel alanlarda basit bir sınıf oluşturabilirsiniz ve Java'da yöntem yoktur, ancak yine de bir sınıftır ve yine de sözdizimsel olarak ve tıpkı bir sınıf gibi bellek ayırma açısından ele alınır. Java'da yapıları gerçekten yeniden oluşturmanın bir yolu yoktur.


0

Bazen bir yöntemden birden çok değer döndürmek gerektiğinde böyle bir sınıf kullanın. Tabii ki, bu nesne kısa ömürlü ve çok sınırlı görünürlük ile, bu yüzden iyi olmalı.


0

Çoğu şeyde olduğu gibi, genel kural vardır ve sonra belirli koşullar vardır. Belirli bir nesnenin nasıl kullanılacağını bilmek için kapalı, yakalanmış bir uygulama yapıyorsanız, görünürlük ve / veya verimliliği tercih etmek için daha fazla özgürlük kullanabilirsiniz. Kontrolünüz dışındaki kişiler tarafından herkese açık olarak kullanılacak bir sınıf geliştiriyorsanız, alıcı / ayarlayıcı modeline yaslanın. Her şeyde olduğu gibi, sadece sağduyunuzu kullanın. Halkla ilk tur yapmak ve daha sonra onları alıcı / ayarlayıcı olarak değiştirmek genellikle uygundur.


0

En boy yönelimli programlama, atamaları veya getirmeleri yakalamanıza ve onlara mantıksal mantık eklemenize izin verir, ki bu da sorunu çözmenin doğru yoludur. (Herkese açık mı yoksa korumalı mı yoksa paket korumalı mı olmaları gerektiği diktir.)

Böylece, doğru erişim niteleyicisine sahip istenmeyen alanlarla başlarsınız. Program gereksinimleriniz arttıkça, belki doğrulamak, döndürülen nesnenin bir kopyasını oluşturmak için mantık eklersiniz.

Alıcı / belirleyici felsefesi, ihtiyaç duyulmadıkları çok sayıda basit davaya maliyet yükler.

Görünüş stilinin daha temiz olup olmadığı biraz niteldir. Bir sınıftaki değişkenleri görmek ve mantığı ayrı ayrı görmek kolay olurdu. Aslında, Apect odaklı programlama için varoluş nedeni, birçok kaygının kesiştiği ve onları sınıf bedeninde bölümlendirmenin ideal olmadığıdır (giriş yapmak bir örnek olmaktır - eğer günlüğe kaydetmek istiyorsanız, Java sizi yapmanızı ister bir sürü alıcı yazın ve onları senkronize halde tutun, ancak AspectJ size bir astar sağlar).

IDE sorunu kırmızı bir ringa balığıdır. Get / setlerden kaynaklanan okuma ve görsel kirlilik olduğu kadar çok yazım değildir.

Ek açıklamalar ilk bakışta en boy yönelimli programlamaya benzer gibi görünür, ancak AspectJ'deki özlü bir joker karakter benzeri nokta kesme özelliğinin aksine ek açıklama ekleyerek nokta kesimlerini kapsamlı bir şekilde numaralandırmanızı gerektirir.

Umarım AspectJ farkındalığı insanların dinamik dillere erken yerleşmesini önler.

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.