Neden ve ne zaman 'statik' bir sınıf yapmalıyım? Sınıflarda 'statik' anahtar kelimenin amacı nedir?


47

Bir staticüyedeki birçok dilde bulunan anahtar kelime, o üyeye erişebilmek için o sınıfın bir örneğini oluşturmamanız gerektiği anlamına gelir. Ancak, bütün bir sınıfı yapmak için herhangi bir gerekçe görmüyorum static. Neden ve ne zaman bir sınıf yapmalıyım static?

Sınıf yapmanın ne faydası olur static? Demek istediğim, statik bir sınıf ilan ettikten sonra, bir kişi hala somutlaştırılmadan erişmek istediği tüm üyelerini statik olarak ilan etmelidir.

Bu, örneğin, Mathsınıflamanın geliştiricilerin kodlarını etkilemeden normal (statik değil) ilan edilebileceği anlamına gelir . Başka bir deyişle, bir sınıfı statik veya normal yapmak, geliştiriciler için şeffaftır.


Func Prog tarzında bir la Rich Hickey kodluyorsanız, bu yararlı olabilir.
Meslek

1
Bence statik sınıflar sadece C # 'nın dilde büyük bir tasarım hatasını gizlemeye çalıştığı bir koltuk değneğidir. Neden bu saçma sapan herşeyin bir sınıf ideolojisi etrafında bir dil oluşturduğunu, ancak ek sözdizimini tanıtmak için, böylece bu gereksiz kısıtlamayı dolandırıp çalışabilirsiniz. Eğer C # başlangıçta serbest fonksiyonlara izin verseydi, statik sınıflara ihtiyaç olmazdı.
saat

Yanıtlar:


32

Sınıfın nasıl kullanıldığını kullanıcılara açıklar. Örneğin, aşağıdaki kodu yazmak tamamen saçma olacaktır:

Math m = new Math();

C # vermez zorunda bu korusun ama hiçbir amaca hizmet beri yanı yaptığını bildiren olabilir. Bazı insanlar (ben dahil) programlama dillerinin (ve API'lerin…) yanlış kullanımı zorlaştırmak için mümkün olduğunca kısıtlayıcı olması gerektiği felsefesine bağlı kalırlar: izin verilen tek işlem daha sonra anlamlı ve (umarım) doğru olanlardır.


3
Bu felsefeye katılmıyorum. Benim sorunum bunun değişmesi gerektiği. Dolayısıyla, daha önce kısıtlamak mantıklı gelse de, kısıtlama gelecekteki ihtiyaçlar için geliştirmemizi engellemektedir. Ve eski sistemle (tüm sınıfları yazıp mühürlediğiniz ve belirttiğiniz) eski sistemle etkileşime girmek zorunda kaldığımız eski kitaplık, yazdığınız kodu genişletmemize veya değiştirmemize olanak sağlamıyor. Sırf sınıfınızı canlandırmak için hiçbir nedeniniz olmadığı için, gelecekte buna ihtiyaç duymayacağım anlamına gelmez. Faydalı bir sınıf belirlemek, mantıklı gelse de geleceği düşünün.
SoylentGray

19
@Chad Sonra kütüphane kötü bir şekilde tasarlanmıştır. Uzatma için tasarlanmayan sınıfları genişletmek sonuçta işe yaramaz, bu nedenle sınıfı sealeden başta sınıf haline getirmek en iyisidir . Tüm insanların bu düşünce ile aynı fikirde olmadığını, ancak yorumların bunu tartışmak için uygun bir yer olmadığını kabul ediyorum. Fakat staticbu problem durumunda bile kendini göstermiyor: somutlaştırmak hiçbir zaman bir anlam ifade System.Mathetmeyecek .
Konrad Rudolph

1
@Konard, eğer Mathsınıfın bütün üyelerini sınıfı statik olarak ilan etmeden statik olarak ilan Mathederseniz, yine de bir somutlaştırmaya gerek kalmadan kullanabilirsiniz.
Saeed Neamati

11
@Saeed - Bu doğru, ancak herhangi bir amaca hizmet etmeyen sınıfı da başlatabilirsiniz. Math sınıfının bir örneğiyle ne yapabilirim ? Sınıfın amacını açıkça göstermek için (bir örneğe gerek yoktur veya aranmaz) static.
Corbin

3
@Saeed Bunu tersine çevirelim: Cevabımı yanlış anladığınız anlaşıldığı için cevabımı tekrar okumanızı öneriyorum: Yorumlarınız cevabımla ilgisi yok. Yazman gerektiğini söylemedim new Math().
Konrad Rudolph

24

StackOverflow'un bu konuyla ilgili harika bir tartışması var . Referans kolaylığı için, yazarı Mark S. Rasmussen adına buraya kopyalayıp yapıştıracağım :

Daha önceki bir konuya statik sınıf düşüncelerimi yazdım :

Statik yöntemlerle doldurulmuş fayda sınıflarını severdim. Fazlalık ve bakım cehennemine neden olacak şekilde uzanacak yardımcı yöntemlerin büyük bir konsolidasyonunu yaptılar. Kullanımı çok kolay, örnekleme yok, elden çıkarma yok, sadece ateş ve unut. Sanırım bu, hizmet odaklı bir mimari yaratma konusundaki ilk isteksiz girişimdi - sadece işlerini yapan ve başka bir şey yapmayan birçok vatansız hizmet. Ancak bir sistem büyüdükçe ejderhalar geliyor.

Polimorfizm

Diyelim ki birlikte mutlu bir şekilde uğultu yapan UtilityClass.SomeMethod yöntemine sahibiz. Birden işlevselliğini biraz değiştirmemiz gerekiyor. İşlevselliklerin çoğu aynıdır, ancak yine de birkaç parçayı değiştirmeliyiz. Statik bir yöntem olmasaydı, bir türev sınıfı yapabilir ve yöntem içeriğini gerektiği gibi değiştirebilirdik. Statik bir yöntem olduğu için yapamayız. Elbette, eski yöntemden önce veya sonra işlevsellik eklememiz gerekirse, yeni bir sınıf oluşturabilir ve bunun içindeki eskisini arayabiliriz - ama bu çok iğrenç.

Arayüz sıkıntıları

Statik yöntemler, mantıksal nedenlerle arayüzler üzerinden tanımlanamaz. Ve statik yöntemleri geçersiz kılmadığımız için, statik sınıflar onları arayüzleri ile geçirmemiz gerektiğinde işe yaramaz. Bu, statik sınıfları bir strateji modelinin bir parçası olarak kullanmamızı sağlar. Arayüzler yerine delegeleri geçerek bazı sorunları çözebiliriz.

Test yapmak

Bu temelde yukarıda bahsedilen arayüzey sıkıntılarıyla el ele gider. Uygulamaları değiştirme yeteneğimiz çok sınırlı olduğundan, üretim kodunu test koduyla değiştirmek konusunda da sorun yaşayacağız. Yine, onları sarabiliriz, ancak gerçek nesneler yerine sarmalayıcıları kabul edebilmemiz için kodumuzun büyük bölümlerini değiştirmemiz gerekecek.

Fosters BLOB'ları

Statik yöntemler genellikle faydalı yöntemler olarak kullanıldığından ve faydalı yöntemler genellikle farklı amaçlara sahip olacağından, hızlı bir şekilde tutarlı olmayan işlevsellik ile doldurulmuş büyük bir sınıfla sonuçlanır - ideal olarak, her sınıfın sistem içinde tek bir amacı olması gerekir. Amaçları iyi tanımlandığı sürece sınıfları beş kat daha fazla tercih ederim.

Parametre sürünme

Başlangıçta, bu küçük sevimli ve masum statik yöntem tek bir parametre alabilir. İşlevsellik büyüdükçe, birkaç yeni parametre eklenir. Yakında isteğe bağlı olan başka parametreler de eklenir, bu nedenle yöntemin aşırı yüklenmesini sağlarız (ya da sadece onları destekleyen dillerde varsayılan değerler ekleriz). Çok geçmeden, 10 parametre alan bir yöntemimiz var. Sadece ilk üçü gerçekten gereklidir, 4-7 parametreleri isteğe bağlıdır. Fakat eğer parametre 6 belirtilmişse, 7-9 doldurulması da gerekir ... Bu statik yöntemin ne yaptığını tek bir amaç için bir sınıf oluşturmuş olsaydık, bunu istenen parametrelerde alarak çözebiliriz. yapıcı ve kullanıcının özelliklerle isteğe bağlı değerleri ayarlamasına veya aynı anda birden çok birbirine bağlı değer ayarlama yöntemleri kullanmasına izin verme. Ayrıca,

Tüketicilerin sebepsiz bir sınıf örneği oluşturmasını talep etme

En yaygın argümanlardan biri, neden sınıfımızın tüketicilerinin bu tek bir yöntemi çağırmak için bir örnek yarattığını ve sonradan örneği kullanmayacak olmasının neden talep edilmesidir? Bir sınıfın örneğini oluşturmak çoğu dilde çok ucuz bir işlemdir, bu nedenle hız sorun değildir. Tüketiciye fazladan bir kod satırı eklemek, gelecekte çok daha sürdürülebilir bir çözümün temelini atmak için düşük maliyetlidir. Ve son olarak, örnek oluşturmaktan kaçınmak istiyorsanız, sınıfınızın kolayca yeniden kullanılmasını sağlayan tek bir sarmalayıcı oluşturun - bu, sınıfınızın vatansız olması şartını ortaya çıkarsa da. Vatansız değilse de, uzun vadede size tüm avantajları sunarken, yine de her şeyi işleyen statik sarmalayıcı yöntemleri oluşturabilirsiniz. En sonunda,

Sadece bir Sith mutlak fırsatlar

Tabii ki, statik yöntemlerden hoşlanmadığım için istisnalar var. Şişirme riski oluşturmayan gerçek hizmet sınıfları, statik yöntemler için mükemmel durumlardır - bir örnek olarak System.Convert. Projeniz gelecekteki bakım için gerekliliklere sahip olmayan bir kerelikse, genel mimari gerçekten çok önemli değil - statik veya statik değil, gerçekten önemli değil - geliştirme hızı da öyle.

Standartlar, standartlar, standartlar!

Örnek yöntemlerin kullanılması, statik yöntemlerin kullanılmasını da engellemez ve bunun tersi de geçerlidir. Farklılaşmanın arkasında bir sebep olduğu ve standart olduğu sürece. Farklı uygulama yöntemleriyle yayılan bir iş katmanına bakmaktan daha kötü bir şey yoktur.


12
Hmmm, cevapların tamamını buraya kopyalayıp yapıştıracağımı bilmiyorum. Belki bağlantı ve parola, bir "tartışma" dan bahsettiğinizden beri kendi deneyiminizi paylaşan alternatif bir bakış açısı içerir?
Corbin

2
"Sadece bir Sith mutlaklıklarla uğraşır" - daha önce böyle kullanıldığını görmemiştim .... ama MÜKEMMEL. Bana lol yaptı.
Brook

4
@ Corbin: Mark harika bir cevabı vardı. Ona kredi verdim ve referans kolaylığı için kopyaladım / yapıştırdım. Bu konudaki kendi görüşlerim Mark's ile aynı. Tartışmaya başlamaktan başka, yorumunuzun amacını görmüyorum.
Rick

1
@Rick: Kopyalanan cevap oldukça uzun ve kesinlikle parantez atmaya yardımcı olacak. "Sadece gerçekten yararlı olmadıkları değil, SO'nun yazdığı gibi gösterebileceği gibi bile zarar verebilirler" gibi bir cümle, aradığım bilgiyi göremediğim için çabucak atlamama izin verirdi.
blubb

@Simon: LOL Yazınızı 1 + 'ledi. Çok aptalca bir şeyi tartışmaktan vazgeçme teşebbüsünde, sadece katılıyorum. :) Umarım orijinal poster benim cevap / kopyala yapıştır yapıştırıcısını faydalı buldu.
Rick

16

Başka hiç kimsenin staticsınıfların uzatma yöntemlerine izin vermediğinden - sahip olmadığınız bir türün ( arayüzlere yöntem tanımları eklemek de dahil) güvenli şekilde genişletildiğinden bahsetmediğine şaşırdım . Mesela Scala’da ne var

trait MyFoo {
  def foo: Int
  def plusFoo(a: Int) = foo + a
}

olarak C # ile ifade edilebilir

public interface IMyFoo {
  int Foo();
}

public static class MyFooExtensions {
  public static int PlusFoo(this IMyFoo f, int a) {
    return f.Foo() + a;
  }
}

samanlıkta iğne buldun. +1
Saeed Neamati

3

Benim için, statik bir sınıf (C #) bir işlevi çağırmak gibi bir şey.

Örneğin

public static string DoSomething(string DoSomethingWithThisString){}

Bir dizgeye geçip bir dizgiye dönüyorum Her şey bu yöntemde yer almaktadır. Üye değişkenine vb. Erişim yok.

Dürüst olmak gerekirse, çoğunlukla benim için kullanımı kod satırlarını azaltmaktı:

Neden yapmak:

MyClass class = new MyClass();
String s = class.DoSomething("test");

Bunu ne zaman yapabilirim:

String s = MyClass.DoSomething("test");

Dolayısıyla, bu durumlarda statik sınıfları kullanırdım, bir sınıfa ihtiyaç duymadan bir şeyler yapmak istediğimde ve daha az yazı yazmak istediğimde.

Mark S. puanları geçerlidir, ancak benim için bazı yardımcı yöntem yöntemlerine sahipsem, sadece bir gömlek olarak adlandırmak için bir işlev çağırdığımı iddia etmek daha kolay.

Bu basit olabilir, ama çoğunlukla böyle kullandım static.


1
Yeni Sınıfım (). DoSomething ("test") hala geçerlidir. Bunu Test Veri Oluşturucuları için çok kullanıyorum.
JoanComasFdz
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.