Önemli miktarda zaman, statik bir sınıf yerine bir nesneye sahip olmak için bir neden düşünemiyorum. Nesnelerin düşündüğümden daha fazla faydası var mı? [kapalı]


9

Bir nesne kavramını anlıyorum ve bir Java programcısı olarak OO paradigmasının pratikte bana oldukça doğal geldiğini hissediyorum.

Ancak son zamanlarda kendimi düşünürken buldum:

Bir saniye, bir nesneyi statik bir sınıf (uygun kapsülleme ve OO uygulamalarıyla) kullanmanın pratik faydaları nelerdir?

Bir nesneyi kullanmanın iki faydasını düşünebilirim (her ikisi de önemli ve güçlüdür):

  1. Çok biçimlilik: çalışma sırasında işlevselliği dinamik ve esnek bir şekilde değiştirmenize olanak tanır. Ayrıca sisteme kolayca yeni işlevler 'parçalar' ve alternatifler eklemenize izin verir. Örneğin Car, Enginenesnelerle çalışmak üzere tasarlanmış bir sınıf varsa ve Aracın kullanabileceği sisteme yeni bir Motor eklemek istiyorsanız, yeni bir Enginealt sınıf oluşturabilir ve bu sınıftaki bir nesneyi nesneye nesnelere iletebilirsiniz Car. hakkında bir şey değiştirmek Car. Ve bunu çalışma zamanı sırasında yapmaya karar verebilirsiniz.

  2. 'İşlevsellikten geçebilme': sistem etrafında bir nesneyi dinamik olarak geçirebilirsiniz.

Ancak statik sınıflara göre nesnelere daha fazla avantajı var mı?

Genellikle bir sisteme yeni 'parçalar' eklediğimde, bunu yeni bir sınıf oluşturarak ve ondan nesneleri somutlaştırarak yaparım.

Ancak son zamanlarda durup düşündüğümde, statik bir sınıfın normalde bir nesneyi kullandığım birçok yerde bir nesne ile aynı şeyi yapacağını fark ettim.

Örneğin, uygulamama bir kaydetme / yükleme dosyası mekanizması eklemek için çalışıyorum.

Bir nesneyle, çağıran kod satırı şöyle görünecektir: Thing thing = fileLoader.load(file);

Statik bir sınıfla, şöyle görünecektir: Thing thing = FileLoader.load(file);

Fark ne?

Oldukça sık, sade eski bir statik sınıfın aynı şekilde hareket etmesi durumunda bir nesneyi başlatmak için bir neden düşünemiyorum. Ancak OO sistemlerinde statik sınıflar oldukça nadirdir. Bu yüzden bir şey eksik olmalıyım.

Listelediğim iki nesneden başka nesnelere daha fazla avantaj var mı? Lütfen açıkla.

EDIT: Açıklığa kavuşturmak için. İşlevleri değiştirirken veya verileri aktarırken nesneleri çok kullanışlı buluyorum. Örneğin, melodileri oluşturan bir uygulama yazdım. MelodyGeneratorfarklı melodiler yaratan birkaç alt sınıfa sahipti ve bu sınıfların nesneleri birbirinin yerine kullanılabiliyordu (Strateji modeli).

Melodiler de nesnelerdi, çünkü onları etrafta geçirmek faydalıdır. Akorlar ve Teraziler de öyle.

Peki ya sistemin 'statik' kısımları - etrafa aktarılmayacak? Örneğin - bir 'dosya kaydet' mekanizması. Neden statik bir sınıfta değil de bir nesnede kullanmalıyım?


Yani, alanları ve belki de yöntemleri olan bir nesne yerine, hiçbir nesne, kayıt yok, sadece bir çok skaler değer geçti ve statik yöntemlerden döndü? Düzenleme: Yeni örneğiniz aksini gösteriyor: Nesneler, örnek yöntemleri olmadan mı? Aksi halde, nedir Thing?

FileLoaderBir soketten okunan bir tane için takas etmeniz gerektiğinde ne olur ? Ya da test için bir alay? Veya bir zip dosyası açan?
Benjamin Hodgson


1
@delnan Tamam Cevabın anlamama yardımcı olacağı bir soru anladım: neden sistemin 'statik' bir kısmını nesne olarak uygulasın? Sorudaki örnek gibi: bir dosya kaydetme mekanizması. Bir nesneye uygulamaktan ne kazanırım?
Aviv Cohn

1
Varsayılan, statik olmayan bir nesne kullanmak olmalıdır. Statik sınıfları yalnızca niyetinizi gerçekten daha iyi ifade ettiğini düşünüyorsanız. System.Math.NET'te statik bir sınıf olarak çok daha mantıklı olan bir şeyin örneğidir: asla takas etmeniz veya taklit etmeniz gerekmez ve hiçbir işlem mantıksal olarak bir örneğin parçası olamaz. 'Tasarruf' örneğinizin bu faturaya uygun olduğunu düşünmüyorum.
Benjamin Hodgson

Yanıtlar:


14

lol üzerinde çalıştığım bir takım gibi geliyorsun;)

Java (ve muhtemelen C #) kesinlikle bu programlama stilini destekler. Ve ilk içgüdüleri olan insanlarla çalışıyorum, "Bunu statik bir yöntem yapabilirim!" Ancak zamanla sizi yakalayan bazı ince maliyetler vardır.

1) Java Nesneye Dayalı bir dildir. Ve fonksiyonel adamların fındık kullanıyor, ama gerçekten oldukça iyi duruyor. OO'nun arkasındaki fikir, durumu gizleyerek ve yalnızca bu bağlamda anlamlı olan işlevleri ortaya çıkararak semantiklerini koruyan küçük veri birimleri ve işlevlere sahip olmak için işlevselliği devletle birleştirmektir.

Yalnızca statik yöntemlerle bir sınıfa geçerek denklemin "durum" kısmını kırarsınız. Fakat devlet hala bir yerlerde yaşamak zorunda. Zaman içinde gördüğüm şey, tüm statik yöntemlere sahip bir sınıfın gittikçe daha karmaşık parametre listelerine sahip olmaya başlamasıdır, çünkü durum sınıftan ve işlev çağrılarına geçmektedir.

Tüm statik yöntemlerle bir sınıf oluşturduktan sonra, bu yöntemlerden kaç tanesinin tek ve ortak bir parametreye sahip olduğunu araştırın. Bu parametrenin, bu işlevler için kapsayıcı sınıf olması ya da bu parametrenin bir örneğin özniteliği olması gerektiğini gösteren bir ipucudur.

2) OO kuralları oldukça iyi anlaşılmıştır. Bir süre sonra bir sınıf tasarımına bakabilir ve SOLID gibi kriterleri karşılayıp karşılamadığını görebilirsiniz. Birçok pratik birim testinden sonra, bir sınıfı "doğru" ve "tutarlı" kılan şeyin ne olduğuna dair iyi bir fikir geliştirirsiniz. Ancak, tüm statik yöntemlere sahip bir sınıf için iyi kurallar yoktur ve orada her şeyi bir araya getirmemenizin gerçek bir nedeni yoktur. Sınıf editörünüzde açık, ne halt? Yeni yönteminizi buraya ekleyin. Bir süre sonra, uygulamanız her biri dünyaya hükmetmeye çalışan bir dizi rakip "Tanrı Nesnesi" ne dönüşür. Yine, onları daha küçük birimlere dönüştürmek oldukça özneldir ve doğru olup olmadığını söylemek zordur.

3) Arabirimler Java'nın en güçlü özelliklerinden biridir. Sınıf mirasının sorunlu olduğu kanıtlanmıştır, ancak arayüzlerle programlama dilin en güçlü numaralarından biri olmaya devam etmektedir. (ditto C #) Tüm statik sınıflar kendilerini bu modele sokamazlar.

4) Yararlanamayacağınız önemli OO tekniklerine kapıyı vurur. Böylece, tornavidanız olsaydı, işlerin ne kadar kolay olacağını fark etmeden, yıllarca araç kutunuzda sadece bir çekiçle çalışabilirsiniz.

4.5) Mümkün olan en sert, kırılmaz derleme zamanı bağımlılıklarını yaratır. Örneğin, eğer varsa, bunu FileSystem.saveFile()değiştirmenin bir yolu yoktur, JVM'nizi çalışma zamanında taklit etmeksizin. Bu, statik işlev sınıfınıza başvuran her sınıfın, belirli bir uygulamaya zor, derleme zamanı bağımlılığı olduğu anlamına gelir, bu da uzantıyı neredeyse imkansız hale getirir ve testi muazzam bir şekilde karmaşıklaştırır. Statik sınıfı ayrı olarak test edebilirsiniz, ancak o sınıfa başvuran sınıfları ayrı ayrı test etmek çok zorlaşır.

5) İş arkadaşlarınızı delirteceksiniz. Çalıştığım profesyonellerin çoğu kodlarını ciddiye alıyor ve en azından bazı tasarım ilkelerine dikkat ediyor. Bir dilin temel amacını bir kenara bırakmak, kodlarını sürekli olarak yeniden düzenleyecekleri için saçlarını çekmelerini sağlayacaktır.

Bir dildeyken her zaman bir dili iyi kullanmaya çalışırım. Örneğin, Java'dayken iyi bir OO tasarımı kullanıyorum, çünkü o zaman dili gerçekten yaptığı şey için kullanıyorum. Python'deyken, modül düzeyindeki işlevleri zaman zaman sınıflarla karıştırıyorum - sadece Python'da sınıflar yazabildim, ama sonra dilini iyi olan şey için kullanmayacağımı düşünüyorum.

Başka bir taktik, dili kötü kullanmaktır ve neden oldukları tüm problemlerden şikayet ederler. Ancak bu hemen hemen her teknoloji için geçerlidir.

Java'nın temel özelliği, birlikte takılan küçük, test edilebilir birimlerde karmaşıklığı yönetmektir, böylece anlaşılması kolaydır. Java, uygulamadan bağımsız olarak açık arabirim tanımlarını vurgular - ki bu çok büyük bir avantajdır. Bu yüzden (ve diğer benzer OO dilleri) bu kadar yaygın olarak kullanılmaktadır. Tüm ayrıntı ve ritüelizm için, büyük bir Java uygulamasıyla işim bittiğinde, fikirlerin kodda daha dinamik bir dilde projelerimden daha temiz bir şekilde ayrıldığını hissediyorum.

Yine de zor bir soru. İnsanların "tüm statik" hataları aldıklarını gördüm ve onlardan konuşmak biraz zor. Ama üstesinden geldiklerinde büyük bir rahatlama hissi olduğunu gördüm.


Esas olarak işleri küçük ve modüler tutmak ve durumu ve işlevselliği bir arada tutmaktan bahsediyorsunuz. Bunu statik sınıflarla yapmamı engelleyen hiçbir şey yok. Devleti olabilir. Ve onları getters-setters ile kapsülleyebilirsiniz. Sistemi işlevselliği ve durumu kapsayan küçük sınıflara bölebilirsiniz. Bütün bunlar hem sınıflar hem de nesneler için geçerlidir. Ve bu tam olarak benim açmazım: Uygulamama yeni işlevler eklediğimi söyle. Açıkçası SRP'ye itaat etmek için ayrı bir sınıfa gidecek. Ama neden bu sınıfı somutlaştırmalıyım? Anlamadığım şey bu.
Aviv Cohn

Demek istediğim: bazen nesneleri neden istediğim açık. Düzenlemeden soruma örnek kullanacağım: Melodileri oluşturan bir uygulamam vardı. Farklı melodiler oluşturmak için MelodyGenerators'a ekleyebileceğim farklı Ölçekler vardı. Ve Melodiler nesnelerdi, bu yüzden onları bir yığına koyabilir ve eski olanları oynamak için geri dönebilirim. Böyle durumlarda neden nesneleri kullanmam gerektiği açık. Anlamadığım şey neden sistemin 'statik' bölümlerini temsil etmek için nesneleri kullanmalıyım: örneğin bir dosya kaydetme mekanizması. Neden bu sadece statik bir sınıf olmasın?
Aviv Cohn

Statik yöntemlere sahip bir sınıf, durumunu dışsallaştırmalıdır. Bu bazen çok önemli bir faktoring tekniğidir. Ancak çoğu zaman durumu kapsüllemek istersiniz. Somut bir örnek: yıllar önce bir iş arkadaşı Javascript'te bir "tarih seçici" yazdı. Ve bu bir kabustu. Cusomers sürekli şikayet etti. Bu yüzden onu "takvim" nesnelerine doğru yeniden düzenledim ve birden bire onları yan yana koydum, yan yana koydum, aylar ve yıllar arasında atladım, vb. Örnekleme size bu ölçeği verir.
Rob

3
"OO'nun arkasındaki fikir, durumu gizleyerek ve yalnızca bu bağlamda anlamlı olan işlevleri ortaya çıkararak anlambilimlerini koruyan küçük veri ve işlevselliklere sahip olmak için işlevselliği devletle birleştirmektir." Bu temelde yanlış. OO değişebilir durum anlamına gelmez ve soyutlama OO'ya özel değildir. Soyutlamaya ulaşmanın iki yolu vardır ve nesneler bunlardan sadece biridir (diğeri soyut veri türleridir).
Doval

1
@ Düşürme OO'nun her tartışmasının neden fonksiyonel programlama tartışmasına dönüşmesi gerektiğini anlamıyorum.
Rob

6

Sen sordun:

Ancak statik sınıflara göre nesnelere daha fazla avantajı var mı?

Bu sorudan önce, Polimorfizm ve Nesnelerin kullanılmasının iki yararı olarak aktarılmayı listelediniz . Bunların OO paradigmasının özellikleri olduğunu söylemek istiyorum. Kapsülleme OO paradigmasının bir başka özelliğidir.

Ancak, bunlar fayda değildir. Avantajları:

  1. Daha iyi soyutlamalar
  2. Daha iyi bakım
  3. Daha iyi test edilebilirlik

Dedin:

Ancak son zamanlarda durup düşündüğümde, statik bir sınıfın normalde bir nesneyi kullandığım birçok yerde bir nesne ile aynı şeyi yapacağını fark ettim.

Sanırım burada geçerli bir nokta var. Özünde programlama, verilerin dönüştürülmesinden ve verilere dayalı yan etkilerin yaratılmasından başka bir şey değildir. Bazen verileri dönüştürmek için yardımcı veriler gerekir. Diğer zamanlarda değil.

İlk dönüşüm kategorisiyle uğraşırken yardımcı verilerin ya giriş olarak iletilmesi ya da bir yerde saklanması gerekir. Bir Nesne, bu tür dönüşümler için statik sınıflara göre daha iyi bir yaklaşımdır. Bir Nesne yardımcı verileri saklayabilir ve doğru zamanda kullanabilir.

İkinci dönüşüm kategorisi için, statik bir sınıf daha iyi olmasa da bir Object kadar iyidir. Matematiksel fonksiyonlar bu kategorinin klasik örnekleridir. Standart C kitaplığı işlevlerinin çoğu da bu kategoriye girer.

Sen sordun:

Bir nesneyle, çağıran kod satırı şöyle görünecektir: Thing thing = fileLoader.load(file);

Statik bir sınıfla, şöyle görünecektir: Thing thing = FileLoader.load(file);

Fark ne?

Eğer FileLoaderdeğil, şimdiye kadar , ikinci yaklaşım ile gider, herhangi bir veri depolamak gerekiyor. İşlemi gerçekleştirmek için yardımcı verilere ihtiyaç duyma şansının bir çeşidi varsa, ilk yaklaşım daha güvenli bir bahistir.

Sen sordun:

Listelediğim iki nesneden başka nesnelere daha fazla avantaj var mı? Lütfen açıkla.

OO paradigmasını kullanmanın faydalarını (avantajlarını) listeledim. Umarım kendileri açıklayıcıdır. Değilse, detaylandırmaktan memnuniyet duyarım.

Sen sordun:

Peki ya sistemin 'statik' kısımları - etrafa aktarılmayacak? Örneğin - bir 'dosya kaydet' mekanizması. Neden statik bir sınıfta değil de bir nesnede kullanmalıyım?

Bu, statik bir sınıfın yapmayacağı bir örnektir. Uygulama verilerinizi bir dosyaya kaydetmenin birçok yolu vardır:

  1. Bir CSV dosyasına kaydedin.
  2. Bir XML dosyasına kaydedin.
  3. Bir json dosyasına kaydedin.
  4. Verilerin doğrudan dökümü ile bir ikili dosya olarak kaydedin.
  5. Doğrudan veritabanındaki bazı tablolara kaydedin.

Bu tür seçenekleri sağlamanın tek yolu bir Arayüz oluşturmak ve arayüzü uygulayan Nesneler oluşturmaktır.

Sonuç olarak

Eldeki sorun için doğru yaklaşımı kullanın. Bir yaklaşımdan diğerine karşı dini olmamak daha iyidir.


Birçok farklı nesne türleri (sınıflar) ihtiyaç kaydedilmesini Ayrıca, (örneğin Melody, Chord, Improvisations, SoundSampleve diğerleri), o zaman soyutlamaların yoluyla uygulanmasını kolaylaştırmak için ekonomik olacaktır.
rwong

5

Bazen dile ve bağlama bağlıdır. Örneğin, PHPhizmet istekleri için kullanılan komut dosyalarının her zaman bir hizmet isteği ve komut dosyasının tüm ömrü boyunca üretilecek bir yanıtı vardır, bu nedenle istek üzerinde işlem yapmak ve yanıt oluşturmak için statik yöntemler uygun olabilir. Ancak, üzerinde yazan bir sunucuda Node.js, aynı anda birçok farklı istek ve yanıt olabilir. İlk soru şu - statik sınıfın gerçekten tek bir nesneye karşılık geldiğinden emin misiniz?

İkincisi, tektonlarınız olsa bile, nesneleri kullanmak Dependency_injection ve Factory_method_pattern gibi teknikleri kullanarak polimorfizmden yararlanmanıza izin verir . Bu genellikle çeşitli Inversion_of_control modellerinde kullanılır ve test, günlük kaydı vb. İçin sahte nesneler oluşturmak için kullanışlıdır.

Yukarıdaki avantajlardan bahsettiniz, işte yapmadığınız bir şey: kalıtım. Birçok dilde, örnek yöntemlerin geçersiz kılınabildiği gibi statik yöntemleri geçersiz kılma yeteneği yoktur. Genel olarak, statik yöntemleri devralmak ve geçersiz kılmak çok daha zordur.


Cevabın için teşekkür ederim. Sizce: sistemin 'statik' bir parçasını oluştururken, 'aktarılmayacak' bir şey - örneğin sistemin ses çalan kısmı veya sistemin bir dosyaya veri kaydeden kısmı: bir nesneye mi yoksa statik bir sınıfa mı uygulamalıyım?
Aviv Cohn

3

Rob Y'in gönderisine ek olarak


Sürece senin işlevselliği olarak load(File file)açıkça kullandığınız tüm diğer fonksiyonları ayrılabilmekte, statik bir yöntem / sınıf kullanmak gayet iyi. Devleti dışsallaştırırsınız (kötü bir şey olmayan şey) ve aynı zamanda fazlalık almazsınız, örneğin kendinizi tekrarlamanıza gerek kalmamak için işlevinizi kısmi olarak uygulayabilir veya kırabilirsiniz. (bu aslında bir factorydesen kullanmakla aynı veya benzerdir )

Ancak, bu işlevlerden ikisi ortak bir kullanıma sahip olur olmaz, bunları bir şekilde gruplandırmak isteyebilirsiniz. Sadece bir loadfonksiyonun değil, aynı zamanda bir hasValidSyntaxfonksiyonun olduğunu hayal et . Ne yapacaksın?

     if (FileLoader.hasValidSyntax(myfile))
          Thing thing = FileLoader.load(myfile);
     else
          println "oh noes!"

myfileBuradaki iki referansı görüyor musunuz? Kendinizi tekrarlamaya başlıyorsunuz çünkü harici çağrı durumunuz her çağrı için geçilmelidir. Rob Y, filebu şekilde yapabilmeniz için devleti nasıl içselleştirdiğinizi açıkladı :

     FileLoader myfileLoader = new FileLoader(myfile)
     if (myfileLoader.hasValidSyntax())
          Thing thing = myfileLoader.load();
     else
          println "oh noes!"

Aynı nesnenin iki kez geçmesi yüzeysel bir semptomdur; Dosya iki defa, iki defa açılmış ayrıştırılması gerekebilir ve eğer iki kez kapalı - bu gösterebilecek asıl sorunun bazı işler yedekli olarak yapılmasıdır hasValidSyntax()ve load()yeniden kullanım durumuna (kısmen ayrıştırılmış dosyanın sonuç) izin verilmez.
rwong

2

Statik sınıflar kullanarak başlıca sorunlardan biri de olmasıdır zorlamak için bağımlılıkları gizlemek için size ve zorlamak uygulamalarına bağlıdır sizi. Aşağıdaki kurucu imzasında bağımlılıklarınız nelerdir:

public Person(String name)

İmzadan yola çıkarak, bir kişinin sadece bir isme ihtiyacı var, değil mi? Peki, eğer uygulama:

public Person(String name) {
    ResultSet rs = DBConnection.getPersonFilePathByName(name);
    File f = FileLoader.load(rs.getPath());
    PersonData.setDataFile(f);
    this.name = name;
    this.age = PersonData.getAge();
}

Yani bir kişi sadece somutlaşmış değil. Veriyi bir veritabanından alıyoruz, bu da bize bir dosya yolu ayrıştırmalı ve daha sonra ayrıştırılmalı ve istediğimiz gerçek verilerin alay edilmesi gerekiyor. Bu örnek açıkça üstte, ancak noktayı kanıtlıyor. Ama bekleyin, çok daha fazlası olabilir! Aşağıdaki testi yazıyorum:

public void testPersonConstructor() {
    Person p = new Person("Milhouse van Houten");
    assertEqual(10, p.age);
}

Bu geçmeli, değil mi? Yani, diğer tüm şeyleri kapsadık, değil mi? Aslında bir istisna ile patlar. Neden? Oh, evet, bilmediğimiz gizli bağımlılıklar küresel devlete sahip. DBConnectionİhtiyaçları başlatıldı ve bağlanmalıdır. FileLoaderBir ile başlatılır ihtiyaçları FileFormat(benzer bir objeye XMLFileFormatveya CSVFileFormat). Bunları hiç duymadınız mı? Mesele bu. Statik çağrılar bu bağımlılıkları gizlediğinden kodunuz (ve derleyiciniz) size bunlara ihtiyacınız olduğunu söyleyemez. Test mi dedim? Yeni yeni geliştiricinin en son sürümünüzde böyle bir şey gönderdiği anlamına geliyordum. Sonuçta, derlenmiş = çalışır, değil mi?

Ayrıca, çalışan bir MySQL örneği olmayan bir sistemde olduğunuzu varsayalım. Veya bir Windows sisteminde olduğunuzu ancak DBConnectionsınıfınızın yalnızca bir Linux kutusundaki (Linux yollarıyla) MySQL sunucunuza gittiğini varsayalım. Veya, tarafından döndürülen yolun DBConnectionsizin için okunma / yazmadığı bir sistemde olduğunuzu varsayalım . Bu, bu sistemi bu koşullardan herhangi biri altında çalıştırmaya veya test etmeye çalışmanın, bir kod hatası nedeniyle değil, kodun esnekliğini sınırlayan ve sizi bir uygulamaya bağlayan bir tasarım hatası nedeniyle başarısız olacağı anlamına gelir.

Şimdi, diyelim ki, veritabanına yapılan her çağrıyı Person, belirli ve sorunlu bir yoldan geçen belirli bir örnek için kaydetmek istiyoruz . Giriş yapabiliriz DBConnection, ancak bu her şeyi kaydeder, çok fazla dağınıklık yaratır ve izlemek istediğimiz belirli kod yolunu ayırt etmeyi zorlaştırır. Bununla birlikte, bir DBConnectionörnekle bağımlılık enjeksiyonu kullanıyorsak , arayüzü bir dekoratöre uygulayabiliriz (ya da her iki seçeneğimiz de bir nesne ile mevcut olduğundan sınıfı genişletebiliriz). Statik bir sınıfla, bağımlılığı enjekte edemeyiz, bir arayüz uygulayamayız, bir dekoratöre satamayız ve sınıfı genişletemeyiz. Sadece doğrudan, kodumuzun derinliklerinde gizli bir yerde çağırabiliriz. Böylece zorlandık bir uygulamaya gizli bir bağımlılığa sahip olmak.

Bu her zaman kötü mü? Mutlaka değil, ancak bakış açınızı tersine çevirip "Bunun bir örnek olmamalı iyi bir nedeni var mı ?" "Bunun bir örnek olması için iyi bir neden var mı ?" Kodunuzun Math.abs()hem uygulamasında hem de kullanılacak şekilde değişmez (ve vatansız) olacağını gerçekten söyleyebiliyorsanız, bunu statik hale getirmeyi düşünebilirsiniz. Bununla birlikte, statik sınıflar üzerinde örneklere sahip olmanız, gerçeğin ardından yeniden yakalanması her zaman kolay olmayan bir esneklik dünyası sunar. Ayrıca, kodunuzun bağımlılıklarının gerçek doğası hakkında daha fazla netlik sağlayabilir.


Gizli bağımlılıklar son derece iyi bir nokta. "Kod kalitesinin nasıl uygulandığından değil, nasıl kullanıldığından yargılanması gerekir" deyimini neredeyse unutuyordum.
Euphoric

Ancak statik olmayan bir sınıfta gizli bağımlılıklar da var olabilir mi? Bu yüzden bunun neden statik sınıfların bir dezavantajı olduğunu anlamıyorum ama statik olmayan sınıfların değil.
valenterry

@valenterry Evet, statik olmayan bağımlılıkları da gizleyebiliriz, ancak kilit nokta statik olmayan bağımlılıkları gizlemenin bir seçim olmasıdır . I could new(genellikle tavsiye edilmez) yapıcısı içinde bir grup nesne yukarı, ama can onlara iğne yapmak da. Statik sınıflarla, onları enjekte etmenin bir yolu yoktur (yine de Java'da kolayca değil ve buna izin veren diller için başka bir tartışma olurdu), bu yüzden başka seçenek yok. Bu yüzden cevaplarımda bağımlılıkları çok fazla gizlemeye zorlanma fikrini vurguluyorum .
cbojar

Ama olabilir argümanlar olarak sağlayarak Onlara yöntemini çağırın her zaman enjekte edin. Bu yüzden onları gizlemek zorunda değilsiniz, ancak herkesin açıkça görmesini sağlamak zorundasınız, böylece herkes "aha, bu yöntem bu argümanlara bağlıdır" yerine "aha, bu yöntem bu (bu) argümanlara ve yapmadığım bazı gizli interal duruma bağlıdır "biliyorum.
valenterry

Java'da, en iyi bildiğim kadarıyla, bütün bir yansıma düzeneğinden geçmeden parametre olarak statik bir sınıf sağlayamazsınız. (Düşünebildiğim her yolu denedim. Eğer bir yolunuz varsa, onu görmek isterim.) Ve bunu yapmayı seçerseniz, ya yerleşik tip sistemini altüst edersiniz (parametre bir Class, o zaman doğru sınıf olduğundan emin oluruz) veya ördek yazıyorsunuz (doğru yönteme yanıt verdiğinden emin oluyoruz). İkincisini yapmak istiyorsanız, dil seçiminizi yeniden değerlendirmelisiniz.
İlkini

1

Sadece iki sentim.

Sorunuz için:

Peki ya sistemin 'statik' kısımları - etrafa aktarılmayacak? Örneğin - bir 'dosya kaydet' mekanizması. Neden statik bir sınıfta değil de bir nesnede kullanmalıyım?

Sen kendine sor eğer sesleri oynar sistemi veya bir dosya verileri kaydeder sistemin bir parçası parçası mekanizması OLACAK DEĞİŞİKLİĞİ . Cevabınız evet ise, abstract class/ ile özetlemeniz gerektiğini gösterir interface. Sorabilirsiniz, gelecekteki şeyleri nasıl bilebilirim? Kesinlikle yapamayız. Yani, eğer durum vatansız ise java.lang.Math, aksi takdirde, nesne yönelimli yaklaşım kullanmak gibi 'statik sınıf' kullanabilirsiniz.


Yanakta bir dil tavsiyesi var: Üç grev ve refactor , bu da değişikliğe gerçekten ihtiyaç duyulana kadar dayanabileceğini gösteriyor. "Değişim" ile kastettiğim: birden fazla nesnenin kaydedilmesi gerekiyor; veya birden fazla dosya biçimine (depolama türü) kaydetme ihtiyacı; veya kaydedilen verilerin karmaşıklığında büyük bir artış. Tabii ki, değişimin yakında gerçekleşeceğinden oldukça eminseniz, daha esnek bir tasarım ön plana çıkarılabilir.
rwong
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.