'Statik fonksiyonlar' ne zaman kullanılır?


24

Tamam, statik bir fonksiyonun ne olduğunu öğrendim, fakat neden özel üye fonksiyonlarından daha faydalı olduklarını hala göremiyorum. Bu, burada bir nevi yeni-soru olabilir, fakat neden sadece tüm özel üye işlevlerini statik işlevlerle değiştirmiyorsunuz?


1
Bu, "tüm statik işlevleri özel üye işlevleriyle değiştir" mi olmalı? Şu anda, statik yöntemlerin noktasını görmediğinizi ve neden daha fazlasını kullanmadığımızı sormaya devam ettiğinizi belirtiyorsunuz.

5
"Statik fonksiyon" nedir? C ++ 'da en az iki anlam var (ve son olarak C ++ 11 taslaklarına baktım, staticfonksiyonların dosya kapsamı ile sınırlandırılması için itiraz bildirimini kaldırdılar .
David Thornley

C / C ++ 'da dosya kapsamındaki statik serbest işlev veya "statik memenber işlevi / yöntem" olarak "statik işlev" anlamına mı geliyorsunuz? Bu büyük fark!
Jan Hudec

@JanHudec: Bence private memberOP'nin güvenli bir şekilde OO kavramı hakkında soru sorduğunu varsayabiliriz ve dosya kapsamı statikiyle ilgili hiçbir fikri yoktur.
Matthieu M.

@MatthieuM .: Aslında 'özel üyenin' varlığı, C ++ anlamında statik işlevler anlamına geldiğine inanmamı sağlayan şeydi. Çünkü dosya kapsamındaki statik fonksiyonlar ve özel üye fonksiyonları, C ++ 'ta çok benzer kullanımı olan iki şey olduğundan, genel statik üyeyi özel statik olmayan üyeyle değiştirmek pek mantıklı gelmez. Maalesef OP cevap vermiyor gibi görünüyor.
Jan Hudec

Yanıtlar:


24

OOP kullandığınızı varsayarsak , herhangi bir sınıf üyesine bağlı olmadıklarında statik işlevler kullanın. Hala özel olabilirler, ancak bu şekilde ilgili nesnenin hiçbir örneğine bağlı olmadıklarından optimize edilirler.

Yukarıdakilerin dışında, üzerinde yalnızca bir genel işlevi yürütmek için bir nesnenin örneği oluşturmak istemediğiniz zaman statik işlevleri yararlı buluyorum. Bu esas olarak, bazı tekrarlayan ve genel çalışmalar yapmak için ortak işlevler içeren yardımcı sınıflar için geçerlidir, ancak çağrılar arasında herhangi bir durumu korumanız gerekmez.


Teşekkürler Bernard. BTW, bir derleyicinin "sınıfa bir yöntem bağlama" için ne anlama geldiğini biliyor musunuz?
Karanlık Tapınak

@Dark Templar: Yaptığımı söyleyemem. Bu, belirli bir dile özgü mü?
Bernard,

"Sınıf üyelerine bağlı değillerdir" tanımınızla ilgili küçük bir problemim var. Üye statik işlevleri, statik olmayan herhangi bir üyeye erişemez, ancak statik üyelere erişebilir. Statik üyeler sınıfın üyeleridir.
newprint

@newprint: Haklısınız, ancak söylediğim bu değil. Dediğim zaman herhangi sınıf üyelerine bağımlı olmayan. Gerekirse statik üyeler kullanmak iyidir, ancak bu her zaman böyle olmayabilir.
Bernard

8

Yukarıdakilerden daha basitleştirilmiş bir açıklama yapmaya çalışıyorum (oldukça iyi olanlar).

Bir nesne normalde kod + veridir. Statik bir yöntem yalnızca ilgilenilecek "kod" kısmına sahip olduğunuzda kullanılır (korunan veri / durum yoktur (statik veri üyeleri hariç)).


5

Çünkü onlar bir örneğe ihtiyaç duymuyorlar ve herkese açık olabilirler. En büyük ortak payda almak için bir işleve ihtiyacınız olduğunu söyleyin (GCD; kesir sınıfları için çok faydalıdır ve evet bu basit bir örnektir). Tek amacı, thisihtiyaç duymadığınız veya kullanmadığınız bir işaretçiye sahip olabilmenizdir gcd. Dolayısıyla, ideal olarak GCD'yi kullanan sınıfta (örneğin, kesir sınıfında) statik bir yöntem kullanırsınız.

Tabii ki sadece statik yöntemler varsa, OOP'yi yanlış yapıyorsunuzdur ve ya gerçekten OOP yapmaya ya da paradigmanıza daha uygun bir dil kullanmaya geçmelisiniz.


Örnekte ücretsiz bir işlev kullanmak daha iyi olmaz mıydı?
Ela782

2
@ Ela782 Dil ücretsiz fonksiyonlara sahipse, evet.

Tamam, güvence için teşekkürler. Bu en iyi uygulamayı sadece son zamanlarda öğrendim. Ancak, o zaman şu anda bir genel statik üye fonksiyonunun ne zaman faydalı olabileceğini görmekle ilgili sorun yaşıyorum, diyelim ki C ++ gibi bir dilde. Her ikisinde de kullanım durumu, işlevin sınıfın bir örneğine bağlı olmadığı veya gerekmediği durumdur ve ardından serbest işlevler öneridir. Belki bu yeni bir soru olmalı.
Ela782

1
@ Ela782 Evet, güzel bir soru yapabilir. İki hızlı nokta: Özellikle C ++ 'da statik üyeler şablon meta programlaması için kullanışlıdır çünkü bir türü şablon parametresi olarak geçirebilirsiniz, ancak bir ad alanı değil. Sadece (düşünmek bir ad alanında mensup aksine Genelde, statik fonksiyonlar, fonksiyon gerçekten yakından bazı sınıfa ait olduğunu belirtmek için kullanılabilir stuff::Thing::Load(...)vs stuff::LoadThing()).

2

Bunları ortak görevlerde yardımcı işlevler olarak kullanıyorum, örnekler:

  • Dereceleri radyanlara dönüştürme (ve tersi);
  • Bir dize karma;
  • Bir enumdan başka bir şeye dönüştürme (bu projede çalışıyorum, bir karma tablo gibi davranıyorlar);

Statik fonksiyonları gruplayan dosyalarımın çoğunda Yardımcı olan eki var, bu onların yaptıkları anlamına geliyor, daha hızlı bir yere ulaşmama yardımcı oluyor.


2

Statik bir yöntemin ne olduğuna gelince:

Statik yöntemler ne sınıfın bir örneğini gerektirmez ne de böyle bir örneğin verisine (veya bu, ben, Ben vb.) Dolaylı olarak erişemezler. [ 1 ]

Statik yöntemlerin ne zaman faydalı olduğu örnekleri:

  • Global / yardımcı yöntemler
  • Veri Modeli sınıfından sorgu sonuçları alma (SP çağırma)

Sadece uygun olan yerlerde kullanın.

  1. Kendinizi aynı nesneleri birden fazla nesneye kopyalarken bulursanız, yöntemi statik hale getirerek DRY'yi takip etmeyi düşünün.
  2. Bir nesnenin örneğine gerek duymuyorsanız statik yöntemler kullanın (üzerinde çalışma yapmıyorsunuz ve nesnenin örnek değişkenleri)

Verilerinizin çoğu nesnelerin dışındaysa ve statik yöntemlerle çalışıyorsa kodunuz nesne yönelimli değildir ve bakımı zor olabilir.


1

Statik ve özel aslında ortogonaldir: bir yöntem statik, özel veya hiçbiri veya her ikisi de olabilir.

Statik ve statik olmayan (aka 'örnek yöntemleri'), yöntemin sınıfın kendisinde (statik) veya belirli bir örnekte (statik olmayan) çalışıp çalışmadığını gösterir. Dile bağlı olarak, bir örnek üzerinden statik bir yöntem çağırabilirsiniz, ancak örneğe asla statik bir yöntemle erişemezsiniz (bu, statik bir yöntemden statik olmayan bir yöntemi çağıramayacağınız anlamına da gelir; thisnesne). Kavramsal olarak sınıfa bağlanan ancak belirli bir örneğe 'bağlanmayan' davranışı uygulamak için statik yöntemler kullanın. Statik yöntemleri kullanmak isteyebileceğiniz başka bir senaryo ise, bir sınıfın iki örneğinde çalışan bir işleve sahip olduğunuz ve işlenenin hiçbirinin ayrıcalıklı bir durumu haketmediğidir (örneğin, bir sınıfınız olduğunu varsayarsak).Vectorve siz de ekleme yapmak istiyorsunuz; ekleme yönteminiz olarak adlandırılabilir a.Add(b), ancak Vector.Add(a, b)muhtemelen daha mantıklıdır.

Özel veya kamusal , yöntemin görünürlüğü ile ilgilidir. Özel yöntemlere yalnızca sınıfın kendi kapsamı dahilinde erişilebilirken, genel yöntemlere her yerden erişilebilir. Bunun için en önemli kullanım, kapsüllemedir: yalnızca, sınıfınızla iletişim kurmak için kodun geri kalanının mutlaka ihtiyaç duyduğu yöntemleri ve özellikleri halka açarak, dış kodun sorun çıkarabileceği noktaları sınırlarsınız ve içindeki sorunları önlersiniz. Sınıfın projenin geri kalanına kanamadan.

Yani, kural:

  • sınıf dışından çağrılması gerekenler dışındaki tüm üye işlevlerini özel kılmak
  • sınıfın hiçbir örneği olmadığında bile mantıklı olmadıkça tüm yöntemleri örnek yöntemlerini uygulayabilirler.

0

Utility sınıfları için hem C ++ hem de C # öğelerinde statik yöntemler, örnek verisine sahip olmayan sınıflar, yararlı, ilgili yöntemlerden oluşan bir koleksiyonu bir araya getirmenin tek yoludur.

int count1 = DBUtil::GetCountOfSlackerEmployees();
int count2 = DBUtil::GetCountOfEmployedSlackers();

0

C ++ 'dan bahsettiğinizi (söylemediyseniz) ve şartlara sahip olduğunuzu varsayalım (yani üye işlevler / yöntemler anlamına gelmez):

Özel bir üye fonksiyonunun bile başlıkta bildirilmesi gerekir, yani kullanıcı aslında çağıramasa da, aslında sınıfın API ve ABI'sının bir parçası olur. Özel üye işlevini ekler, değiştirir veya silerseniz, tüm bağımlı sınıfların yeniden derlenmesini zorlarsınız (başlık değişti, daha iyi yapamazsınız) ve bunu bir kütüphanede yaptığınızda, uygulamanın uyumluluğunu göz önünde bulundurmanız gerekir. o.

Öte yandan, dosya kapsamındaki statik fonksiyonlar genel bir sembol almaz, böylece istediğiniz gibi ekleyebilir, değiştirebilir veya silebilirsiniz ve bir derleme biriminin ötesindeki hiçbir şey etkilenmeyecektir.


0

Genelde, programınız için bir giriş noktası olarak çalışmak üzere statik bir ana bilgisayara ihtiyacınız vardır. Bu önemli olabilir.


0

Statik bir işlev (ve bu terimin farklı dillerde farklı anlamları vardır), çağrılar arasında tutulan herhangi bir durum gerektirmez. Eğer bir sınıfın yaptıklarına kavramsal olarak yakından bağlıysa, onu sınıf fonksiyonu (sınıfta nesne değil) yapın ya da değilse, genel (veya modül düzeyinde) fonksiyonunu yapın. Nesnenin durumuna ihtiyacı yoksa bir nesneye ait değildir.

Her zaman devleti geçiyorsanız, bu gerçekten durumsuz bir işlev değil, sadece durumsuz sözdizimi ile durumsal bir işlev yapıyorsunuz. Bu durumda, muhtemelen çağıran nesneye aittir veya durumu ve davranışları daha iyi hizalamak için bir yeniden düzenleme yapılır.


0

"neden yalnızca tüm özel üye işlevlerini statik işlevlerle değiştirmiyorsunuz?"

... çünkü özel bir üye örnek verilere erişebilir, ancak yalnızca diğer üye işlevlerinde yapılan çağrılarda olmasına izin verebilir. Statik işlev özel olabilir, ancak örnek bir parametre olarak iletilmediği sürece sınıfın bir örneğini değiştiremez veya gösteremez.


0

Henüz kimsenin iyi bir cevap verememesi çok komik. Bunun da olduğundan emin değilim. Muhtemelen mümkün olduğunca az kullanılmaları gerektiği konusunda ipucu olarak almalısınız. OOP yerine tüm prosedürlerin peşindeler.

İşte birkaç örnek:

Sınıf yöntemleri olarak adlandırdıkları Obj-C'de, genellikle nesnenin iade edilmeden önce referans sayma havuzuna konulduğu tahsisat sarmalayıcıları olarak kullanılırlar.

Obj-C'den başka bir örnek, bir sınıf koleksiyonuna yeni bir sınıf kaydetmektir. Diyelim ki her biri bir dosya türünü işleyen bir sınıf grubunuz var. Yeni bir dosya türü için yeni bir sınıf oluşturduğunuzda, dosya türünü belirleyen sınıftaki statik bir yöntem kullanarak derlemeye (genel değişken) kaydedebilirsiniz.

C ++ 'da düşünebileceğim başka bir kullanım da yumuşakça hataları yakalamak. Yapıcı işleviniz, bir istisna atmak dışında başarısız olamaz. Bir hata örneği değişkeni belirleyebilirsiniz, ancak bu her zaman uygun değildir. Bunun yerine, statik bir paketleyicide arızalanabilecek parçaları yapabilir ve ardından yeni nesneyi tahsis edip iade edebilirsiniz, ya da başarısız olduğunda NULL.


0

Bir şeyin sinüsünü hesaplamak istediğinizi varsayalım.

Statik olmadan:

Math math = new Math()
double y = math.sin(x)

Statik ile:

double y = Math.sin(x)

sinStatik olmayan anlam ifade etmiyor . Vatansız ve sadece girdiyi işler.

Statik fonksiyonlar belirli bir nesneye bağlı değildir. Bunlar nesnenin iç durumundan bağımsız "genel" işlevlerdir.


Statik yöntemler değildir "vatansız olması garanti". Örnek verileri kullanamadıkları doğru olsa da, bazı durumlara da (yani statik yöntemin ait olduğu sınıfın her ikisi de, diğer sınıfların statik değişkenleri gibi diğer küresel olarak görünür durumlara) erişebilirler.

@delnan: true ... haklısın. Bunu şimdi düzelteyim.
dagnelies

Statik olmadan: x.sin(). Cevabınız, günahın "Matematik" in bir işlevi olduğunu varsayar, oysa ki açıkça bir çift üzerinde çalışıyor.
AjahnCharles

0

Burada biraz geç kalıyorum, ancak kesin bir tanım oluşturmaya çalışıyorum: statik işlevler, içeren sınıfın örnek özelliklerini / yöntemlerini referans göstermeyen veya gösteremeyen işlevlerdir.

Bazı dillerde, C # gibi, statik sınıflarda statik alanlar veya özellikler olabilir, bu yüzden durum için kullanılmadıklarını söylemek doğru değildir; statik bir fonksiyon statik (global) durumdan yararlanabilir.

Temel olarak, aşağı doğru kayıyor: statik işlevler, statik gibi, statik olmayan örneklere bağımlı olmadan her zaman kullanılabilir olmaları mantıklı olduğunda yararlıdır.

Yardımcı fonksiyonlar, matematik fonksiyonları gibi, açık bir örnek, ancak başkaları da var.

Yarattığınız sınıf verinin değişmez olmasını gerektiriyorsa, bir örneği alan ve örneğin değiştirilemediği (veya değiştirilmemesi) nedeniyle yeni bir örneği geçen statik işlevler oluşturmak mantıklı olabilir. Örneğin, dize sınıfları bir dize (veya 2 veya daha fazla) alan ve yeni bir dize geri ileten statik işlevlere sahip olabilir.

Başka bir neden, küresel bir durumu tutan bir sınıf veya bir tür veri olması olabilir. Statik özelliklerle veya statik sınıftaki alanlarla çalışan statik işlevler olabilir.


0

Başka bir f () statik kullanımına işaret etmek istiyorum.

http://www.parashift.com/c++-faq/named-ctor-idiom.html

Bunu kısaltır: staticişlevler "Adlandırılmış Oluşturucular" oluşturmanıza olanak tanır, yani statik işleve uygun ve kendinden belgeleme adıyla ad verirsiniz ve bu statik işlev yapıcılardan birini çağırır (çünkü yapıcılar aynı adlara sahiptir ve bir çoğu, aralarında ayırt etmek zorlaşır).

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.