it-swarm.asia

Tüm statik yöntemleri kullanamaz mıyım?

Aşağıdaki iki UpdateSubject yöntemi arasındaki fark nedir? Sadece varlıklar üzerinde çalışmak istiyorsanız statik yöntemler kullanmanın daha iyi olduğunu hissettim. Hangi durumlarda statik olmayan yöntemlerle gitmeliyim?

public class Subject
{
    public int Id {get; set;}
    public string Name { get; set; }

    public static bool UpdateSubject(Subject subject)
    {
        //Do something and return result
        return true;
    }
    public bool UpdateSubject()
    {
        //Do something on 'this' and return result
        return true;
    }
}

Bu gerçekten sinir bozucu soru için topluluktan birçok vuruş alacağımı biliyorum ama kendimi sormayı durduramadım.

Kalıtımla uğraşırken bu pratik olmaz mı?

Güncelleme:
Şimdi iş yerimizde oluyor. 5 geliştirici ile 6 aylık bir asp.net web uygulaması üzerinde çalışıyoruz. Mimarımız tüm API'ler için tüm statik yöntemleri kullanmamıza karar verdi. Onun muhakeme statik yöntemler hafif ve sunucu yükünü aşağı tutarak web uygulamaları yararlanır.

65
Alexander

Açık "bu" parametreleri ile statik yöntemlerin en belirgin sorunları ile gideceğim:

  1. Sanal gönderimi ve daha sonra polimorfizmi kaybedersiniz. Türetilmiş bir sınıfta bu yöntemi asla geçersiz kılamazsınız. Tabii ki türetilmiş bir sınıfta new (static) yöntemini bildirebilirsiniz, ancak ona erişen herhangi bir kod tüm sınıf hiyerarşisinden haberdar olmalı ve açık kontrol ve döküm yapmalıdır. tam olarak ne OO kaçının olması gerekiyor.

  2. 1 numaralı bir uzantı türünde, sınıf örneklerini arabirimiyle değiştiremezsiniz, çünkü arabirimler (çoğu dilde) bildiremez static yöntemi.

  3. Gereksiz ayrıntı. Hangisi daha okunabilir: Subject.Update(subject) veya sadece subject.Update()?

  4. Bağımsız değişken denetimi. Yine dile bağlıdır, ancak birçoğu, boş bir başvuru hatasının güvenli olmayan çalışma zamanı koşulları (bir arabellek türü) oluşturmasını önlemek için this bağımsız değişkeninin null olmadığından emin olmak için örtük bir denetim derleyecektir. aşma). Örnek yöntemlerini kullanmıyorsanız, bu denetimi her yöntemin başına açıkça eklemeniz gerekir.

  5. Kafa karıştırıcı. Normal, makul bir programcı static yöntemini gördüğünde, doğal olarak bunun 't geçerli bir örnek gerektiriyorsa (karşılaştırma veya eşitlik yöntemi gibi birden fazla örnek almıyorsa veya null referanslarında çalışabileceği düşünülmedikçe). Bu şekilde kullanılan statik yöntemleri görmek bizi iki ya da üç katına çıkaracak ve 4. ya da 5. kez stresli ve öfkeli olacağız ve ev adresinizi biliyorsak tanrı size yardımcı olacaktır.

  6. Bu bir tür kopyalama. Bir örnek yöntemini çağırdığınızda gerçekte ne olur derleyici veya çalışma zamanı, türün yöntem tablosundaki yöntemi arar ve bağımsız değişken olarak this kullanarak çağırır. Temel olarak derleyicinin yaptıklarını yeniden uyguluyorsunuz. KURU ihlal ediyorsunuz, aynı parametreyi gerekmediğinde farklı yöntemlerde tekrar tekrar tekrar ediyorsunuz.

Örnek yöntemlerini statik yöntemlerle değiştirmek için herhangi bir iyi neden düşünmek zor. Lütfen yapma.

87
Aaronaught

Tam olarak nasıl yaptığınızı hemen hemen tanımladınız OOP ve "bu" bir yapı işaretçisidir. Evet, çalışma zamanı polimorfizmini İnşaat sırasında yapının bir unsuru olarak saklanacak bir işlev işaretçisi belirterek C. Diğer dillerde mevcut olan örnek yöntemleri, sadece başlık altında tam olarak aynı şeyi yapan sözdizimsel şekerdir.Python gibi bazı diller arasında, "self" parametresi açıkça listelenir, ancak bunu çağırmak için özel sözdizimi sizin için miras ve polimorfizmi işler.

13
Karl Bielefeldt

Statik yöntemle ilgili sorun, bir alt sınıfa ihtiyacınız olduğu anda gelir.

Statik yöntemler alt sınıflarda geçersiz kılınamaz, bu nedenle yeni sınıflarınız yöntemlerin yeni uygulamalarını sağlayamaz ve bu da onları daha az kullanışlı hale getirir.

10
user1249

static yöntemini bildirirseniz, yöntemi çalıştırmak için sınıftan bir nesne başlatmanız gerekmez (new anahtar sözcüğünü kullanarak). Ancak, üye değişkenlere başvuramazsınız ayrıca statik olmadıkları sürece, bu durumda bu üye değişkenler sınıfa aittir, sınıfın belirli bir somut nesnesi değil .

Başka bir deyişle, static anahtar sözcüğü, bildirimin sınıf tanımının bir parçası olmasına neden olur; bu nedenle sınıfın tüm örneklerinde tek bir başvuru noktası (sınıftan örneklenen nesneler) olur .

Daha sonra, sınıfınızın birden çok çalışan kopyasını istiyorsanız ve durumun (üye değişkenlerin) çalışan tüm kopyalarınız arasında paylaşılmasını istemiyorsanız (yani her nesnenin kendi benzersiz durumu vardır) bu üye değişkenleri statik olarak bildiremez.

Genel olarak, static sınıflarını ve yöntemlerini yalnızca bir veya daha fazla parametre kabul eden ve bir çeşit nesne döndüren yardımcı programlar oluştururken kullanmalısınız, herhangi bir yan etkisi olmadan (ie sınıftaki durum değişkenlerindeki değişiklikler)

7
Robert Harvey

İnsanların 'statik yöntemlerin kötü tasarım gösterdiğini' iddia etmesinin nedeni yöntemlerden kaynaklanmıyor, aslında statik veriler, üstü kapalı veya açık. Örtük olarak, programdaki dönüş değer (ler) i veya parametrelerinde bulunmayan HERHANGİ bir durumu kastediyorum. Statik bir fonksiyonda durumun değiştirilmesi prosedürel programlamaya bir geri dönüşdür. Ancak, işlev durumu değiştirmezse veya bileşen değişikliklerini durum değişikliği işlevlerine devrederse, aslında yordamsaldan daha işlevsel bir paradigmadır.

Durumu değiştirmiyorsanız, statik yöntemlerin ve sınıfların birçok faydası olabilir. Bir yöntemin saf olmasını ve böylece yan etkilerden arındırılmasını ve hataların tamamen tekrarlanabilir olmasını sağlar. Ayrıca, paylaşılan bir kitaplık kullanan birden fazla uygulamadaki farklı yöntemlerin, aynı girdi verildiğinde aynı sonuçları elde etmelerini sağlayarak hem hata izlemeyi hem de birim sınamasını çok daha kolay hale getirir.

Sonuçta, uygulamada 'StateManager' gibi yaygın olarak görülen büyük boyutlu nesneler ile statik veya global veriler arasında hiçbir fark yoktur. Doğru kullanılan statik yöntemlerin yararı, yazarın durumu daha sonraki revizörlere değiştirmeme niyetini gösterebilmeleridir.

3
Mathieson

Bu, sorduğunuz topluluğa bağlı olarak çok farklı cevaplar alma eğiliminde olan çok ilginç bir soru. Diğer cevaplar C # veya Java önyargı: (çoğunlukla) saf nesne yönelimli ve nesne yöneliminin ne olduğuna dair bir tür deyimsel görünüme sahip bir programlama dili gibi görünüyor.

C++ gibi diğer topluluklarda, nesne yönelimi daha fazla özgürlükle yorumlanır. Bazıları bilir ki uzmanlar konuyu inceler ve aslında, serbest fonksiyonlar kapsüllemeyi iyileştirir (vurgu benimdir):

Bir sınıftaki kapsülleme miktarını ölçmenin makul bir yolunun, sınıfın uygulaması değişirse kırılabilecek işlevlerin sayısını saymak olduğunu gördük. Bu durumda, n üye işlevine sahip bir sınıfın n + 1 üye işlevine sahip bir sınıftan daha kapsüllendiği anlaşılmaktadır. Ve bu gözlem, üye olmayan arkadaş işlevlerini üye işlevlerine tercih etme argümanımı haklı kılan şeydir

Scott Meyers

C++ terminolojisine aşina olmayanlar için:

  • üye işlevi = yöntem
  • üye olmayan işlev = statik yöntem
  • non-friend = yalnızca herkese açık API kullan
  • üye olmayan arkadaş olmayan işlev = yalnızca herkese açık API kullanan statik yöntem

Şimdi, size soruyu cevaplamak için:

Tüm statik yöntemleri kullanamaz mıyım?

Hayır, her zaman statik yöntemler kullanmamalısınız.

Ancak, bunları yalnızca bir sınıfın genel API'sını kullanmanız gerektiğinde kullanmalısınız.

3
authchir

Dile ve ne yapmaya çalıştığınıza bağlı olarak, cevap çok fazla fark olmayabilir, ancak static sürümü biraz daha karmaşıktır.

Örnek sözdiziminizin önerdiği gibi Java veya C #, sanırım Thorbjørn Ravn Andersen geçersiz kılma (geç bağlama ile) sorununu belirtmek için doğru. Statik bir yöntemle, geç bağlamaya dayanır, böylece geç bağlamaya sahip olamazsınız.

Aslında, statik bir yöntem sadece bir modüldeki işlevdir, bu modül sınıfla aynı ada sahiptir - gerçekten bir OOP yöntemi değil).

2
Steve314

Bunu yaparken temelde nesnelerin tüm noktasını yeniyorsunuz. Prosedür kodundan nesne yönelimli koda geçmemiz için iyi bir neden var.

ASLA sınıf türünü parametre olarak alan statik bir yöntem bildiririm. Bu, kodu kazanç elde etmek için daha karmaşık hale getirir.

2
Loren Pechtel

Burada çok büyük cevaplar var ve cevap olarak ortaya koyabileceğim her şeyden çok daha anlayışlı ve bilgili. Ama üzülmeyen küçük bir şey olduğunu hissediyorum:

"Mimarımız tüm API'ler için tüm statik yöntemleri kullanmamıza karar verdi. Akıl yürütme yöntemi statik yöntemler olup hafiftir ve sunucu yükünü düşük tutarak web uygulamalarına fayda sağlar."

(cesur vurgu benimdir)

Sorunun bu bölümündeki benim 2c şudur:

Teorik olarak, söylenenler doğrudur: statik bir yöntem çağırmak, yalnızca bu yöntemi çağırmanın yükünü taşır. Statik olmayan (örnek) bir yöntemin çağrılması, önce nesneyi başlatmanın ve bir noktada örneği yok etmenin ek yüküne sahiptir (kullanılan platforma bağlı olarak manuel veya bir tür otomatik çöp toplama yoluyla).

Bu konuda biraz şeytanın avukatı: daha da ileri gidebiliriz ve şöyle şeyler söyleyebiliriz:

  • (örnek) yönteminin her çağrılması için bir örnek oluşturulursa bu gerçekten kötü olabilir (yalnızca statik olarak bırakıp böyle çağırmak yerine)

  • kurucunun karmaşıklığına, tür hiyerarşisine, diğer örnek üyelere ve diğer bilinmeyen faktörlere bağlı olarak, statik olmayan yöntem çağrısının ekstra yükü değişebilir ve gerçekten büyük olabilir

Gerçekte, IMHO, yukarıdaki noktalar (ve "daha hızlı oldukları için statik kullanalım" genel yaklaşımı saman adam argümanları/değerlendirmeleridir:

  • kod iyiyse ve bu argümana daha spesifikse, örnekler yalnızca gerektiğinde oluşturulduysa (ve en uygun şekilde yok edildiğinde), uygun olduğunda delice yöntemlerini kullanmaktan fazladan ek yük alamazsınız (çünkü yalnızca gerekli nesneleri oluşturun, bu yöntem statik olarak bildirilse bile oluşturulmuş olurdu, bazı yerlerde = aynı örnekleme yükü)

  • statik yöntem bildirimini bu şekilde kötüye kullanarak, örneklerin nasıl oluşturulduğuna ilişkin olarak kodunuzla ilgili bazı sorunları gizlemek mümkündür (yöntem statik olduğu için yanlış bir örnekleme kodu daha sonraya kadar fark edilmeyebilir ve bu asla iyi değildir).

2
Shivan Dragon