Statik anahtar kelimeyi anlama


16

Java, Javascript ve PHP ile geliştirme konusunda deneyimim var.

Sizi C # diliyle tanıştırmak için çok iyi bir kitap olduğunu düşündüğüm Microsoft Visual C # 2010 Adım Adım okuyorum.

Statik anahtar kelimeyi anlamada sorun yaşıyorum. Ne kadar bir sınıf statik ilan edilirse bu kadar anladığım kadarıyla tüm yöntemler ve değişken statik olması gerekir. Ana yöntem her zaman statik bir yöntemdir, böylece sınıfta ana yöntemin var olduğu tüm değişkenler ve yöntemler ana yöntemde çağırmanız gerekiyorsa statik olarak bildirilir. Ayrıca, başka bir sınıftan statik bir yöntem çağırmak için sınıf adını kullanabileceğiniz bir nesne oluşturmanız gerekmediğini fark ettim.

Ancak statik anahtar kelimenin asıl amacı nedir? Statik değişken ve yöntemleri ne zaman bildirmeliyim?


4
C # 'daki static, Java'daki static ile hemen hemen aynıdır. Java ile anlıyorsanız, C #
superM

Java benim ilk programlama dilimdi ve bu kavramı da anlamıyordum. Java'yı sadece kısa bir süre kullandım
Nistor Alexandru

Kısacası, nesne yönüne ihtiyacınız olmadığında "statik" kullanın, örneğin, yalnızca bazı bağımsız yöntemler veya değişkenler. Bir sınıfı statik olarak bildirmek, nesne yönelimli olmayan işlevleri ve değişkeni yalnızca ortak bir adla (boşluk), sınıf adına koymak anlamına gelir.
Doc Brown

Yanıtlar:


15

C # 'daki' statik 'anahtar sözcüğü, sınıftaki tüm sınıflar arasında paylaşılan sınıftaki veya sınıfın kendisindeki bir şeyi ifade eder. Örneğin, statik olarak işaretlenen bir alana, sınıf adıyla o sınıfın tüm örneklerinden erişilebilir.

public class SomeObject
{
    //Static Field
    static int Foo = 3;

    //instance field
    private int _Foo2 = 4;

    //instance property
    public int Foo2{get{return _Foo2;}set{_Foo2 = value;}}


    //static factory method
    public static SomeObject CreateSomeObject(int fooValue)
    {
        SomeObject retVal = new SomeObject();
        retVal.Foo2 = fooValue;
        return retVal;
    }

    //Parameterless instance constructor
    public SomeObject()
    {
    }

    public static int Add(int x)
    {
        //Static methods can only deal with local variables, or fields that
        //  are also static in the class.  This one adds x to the static member foo
        return x + Foo;

        //Foo2 is not accessable here!
    }

      //Instance method
    public int AddSomething(int x)
    {
        //Add x to the property value of Foo2
        return x + this.Foo2;

        //Note that Foo *is* accessable here as 'SomeObject.Foo'
    }

}

Dürüst olmak gerekirse ben asla uzatma yöntemleri (uzantı yöntemleri Hızlı öğretici ) oluşturma dışında statik olarak işaretlenmiş bir sınıf kullanmadım diyebilirim .

Her neyse, fabrika deseni ve singleton deseni gibi statik yöntemleri kullanmak için belirli tasarım desenleri vardır , ancak hatırlanması gereken önemli şey, statik yöntemlerin ve yapıcıların bir sınıfın herhangi bir belirli örneğiyle (bir tane geçmedikçe) ilgilenmemesidir, genellikle hesaplamalar yapmak veya nesneler arasında bir karşılaştırma yapmak. Bahsettiğiniz "Ana" yöntem her zaman statiktir, ancak farklı bir bakış açısından görmek için bu makaleye bakın .

Bunu takip etmek için, statik ve somutlaştırılmış yöntemler, alanlar ve özellikler arasındaki fark nasıl adlandırılır.

public static void Main(string[] args)
{
    //This is a static method that starts a thread in an application
    // space.  At this point not everything actually has to be static...

    //Here is an instantiation with a parameterless contruction
    SomeObject obj = new SomeObject();

    //Here is an instantiation using a static factory method
    SomeObject obj2 = SomeObject.CreateSomeObject(3);

    //Getting field value from static field
    // Notice that this references the class name, not an instance
    int fooValue1 = SomeObject.Foo;

    //Getting property value from instance
    //  Note that this references an object instance
    int fooValue2 = obj2.Foo2;

    //Instance method must be called through an object
    obj2.AddSomething(4);  //if default constructor, would return 8

    //Static methods must be called through class name
    SomeObject.Add(4); //Returns 7
}

Ayrıca, statik sınıflara daha derin bir bakış için bu yazıyı kontrol edin .


19

İşte Joshua Bloch'un açıklamasının yolu, söylediklerinin çoğu gibi parlak buluyorum (evet ben bir Joshua Bloch hayranı çocuğum :)). Bu bellekten alıntılanmıştır.

Bir sınıfın bir ev için mavi baskının eşdeğeri olduğunu düşünün. Öyleyse sınıfın bir örneği sınıf için olduğu için bir evin mavi baskı olduğunu düşünün. Bir sınıfa (mavi baskı) ve ondan birden fazla örneğe (konut) sahip olabilirsiniz.

Şimdi, sağduyu, bir evin (örneğin) mavi baskıda beyan edilmiş olmalarına rağmen sahip olabileceği / davranışlarının çoğunun, o maviden gerçek bir ev (örnek) yapılıncaya kadar kullanılamayacağını belirtir. -baskı (sınıf). Mavi baskınız, içinde ışık anahtarlarının ve ampullerin gitmesi gereken yeri içerebilir, ancak mavi baskıda bu işleri yapmanın bir yolu yoktur, yapabilmek için aslında evi inşa etmeniz gerekir. Işık anahtarını açıp kapatmak ve belirli ampullerin yanmasını ve sönmesini sağlamak için.

Ancak, mavi baskıya doğrudan uygulanabilen ve mavi baskıdan gerçek bir ev yapmanıza gerek kalmadan doğrudan mavi baskıda kullanabileceğiniz / erişebileceğiniz bazı davranışlarınız olabilir. Mavi baskınızın, basıldığında, o mavi baskının içerdiği evin ayak izini gösterecek bir düğmeye sahip olduğunu düşünün (duvarların tüm uzunluklarını ve benzeri hesaplayarak). Açıkçası, önce bir ev inşa edebilir, sonra ayak izini ölçebilirsiniz, ancak bunu sadece mavi baskı ile yapabilirsiniz, bu nedenle bu davranışın mavi baskıda uygulanması daha yararlı olacaktır. Evin kapladığı alanı hesaplayan mavi baskı gibi gömülü bir düğme, bir sınıfta statik bir işleve sahip olmakla eşdeğerdir.


Veya Blueprintplanın ifade ettiği evin kapladığı alanı hesaplama yeteneği de dahil olmak üzere, planın işlevselliğini uygulayan bir sınıfınız olacaktır . Bu plan örneği daha sonra bir plana dayalı olarak Builderpotansiyel olarak isteğe bağlı sayıda Buildingörnek oluşturmak ve çıktısı almak için gerekenleri yapan (buna karşılık muhtemelen bir örnek) beslenir .
CVn

12

Bu şekilde bakmak bana yardımcı olur:

  • Her türün statik bir örneği vardır.
  • Statik örnek, türe ilk eriştiğinizde (statik örnek aracılığıyla veya başka bir örnek oluştururken) oluşturulur.
  • İstediğiniz sayıda statik olmayan örnek oluşturabilirsiniz, ancak yalnızca bir statik örnek vardır.
  • Sınıf içindeki statik olarak bildirilen herhangi bir şey statik örneğe aittir ve bu nedenle oluşturduğunuz diğer örneklere erişimi yoktur. Ancak diğer örneklerin statik örneğe erişimi vardır.
  • Bir sınıf statik olarak bildirilirse, başka örnekler oluşturamazsınız, yalnızca statik örnek var olabilir.
  • Statik örnek için statik bir yapıcıyı, normal bir örnek için bir kurucu gibi (ancak statik olarak bildirerek) bildirebilirsiniz.

Statik anahtar kelimenin ne zaman kullanılacağıyla ilgili olarak:

  • Yerel özelliklere erişim gerektirmeyen herhangi bir yöntem statik olabilir ve muhtemelen bildirilmelidir.
  • Hiçbir şekilde durumu olmayan (zaten nadir olması gereken) ve asla alay edilmeyecek yardımcı sınıflar statik olarak ilan edilebilir. Olmaları gerekip gerekmediği başka bir konudur; bu işlevselliği az miktarda kullanın.
  • Bir sınıfın tüm örnekleri tarafından erişilmesi gereken özellikler ve alanlar statik olarak bildirilmelidir. Ancak bunu yalnızca başka seçenek olmadığında kullanın.

+1, iyi bir özet için, her türün 1 statik örneği olduğunu bilmiyordum ve size gerçeği söylemek garip buluyorum.
NoChance

2
@EmmadKareem Bu sadece pdr'nin kullandığı zihinsel bir model çünkü "Looking at it this way helps"onun için. Garip buluyorsunuz çünkü tam olarak doğru değil, ama isterseniz böyle düşünebilirsiniz. Bohr modelini biliyor musunuz? Atomların ve elektronların birbirleriyle nasıl etkileşime girdiğini gösteren bir dizi kural ve fikir sunar. Modeli ne yapmak bağlı çalışır, ancak gerçeklik değildir.
phant0m

@ phant0m, açıklama için teşekkürler, bunun bir model değil gerçek olduğu izlenimi altındaydım ve bu yüzden şaşırdım.
NoChance

Aslında, bazen staticyerel özellikler kullanmıyor olsa bile, bir yöntem yapmak istemeyebileceğiniz nedenler vardır . Bir şeyler staticyapmak istemcilere kuplaj ekleyebilir, çünkü sınıfı doğrudan ele almaları gerekir. Örneğin, bu, alay ile testin yapılmasını zorlaştırabilir.
Allan

@Allan: Bir sınıfta, o sınıfın bir örneğinin durumunu etkilemeyen genel bir yöntem çağırıyorsanız, bunu istemci geliştiriciye açıklığa kavuşturmak statik olmalıdır. Eğer bu yöntem alay etmeyi gerektirecek kadar çok şey yapıyorsa, bu bir dizi farklı yolla çözülebilecek farklı bir sorundur.
pdr

4

En basit açıklama --- Statik => Ortam başına yalnızca bir kopya olacaktır.

Bu nedenle, bir VM veya CLR içinde statik bir sınıfın yalnızca bir kopyası olacaktır ve onu referans alan diğer herhangi bir sınıf, yöntemlerini ve verilerini referans veren diğer tüm sınıflarla paylaşmalıdır.

Statik bir değişken için, bu değişkenin çalışma süresi ortamında, sahip olan sınıfın kaç kopyası oluşturulduğuna bakılmaksızın, statik bir değişkeni referans aldıklarında, hepsi aynı depolama parçasına başvurursa olsun, yalnızca bir örneği olacaktır.


2

Statik üyeler, bu Sınıfın hiçbir örneğiyle değil, Sınıf ile ilişkilendirilir.

.Net hakkında konuştuğumuzdan, String sınıfını, özellikle de Split ve Join yöntemlerini göz önünde bulundurun .

Split bir örnek yöntemdir. Bir String değişkeni oluşturun, ona bir değer verin ve bu değişken / değer üzerinde Split () öğesini çağırabilir ve bir "bit" dizisini geri alabilirsiniz:

String s1 = "abc,def,ghi" ; 
String[] array2 = s1.Split( ',' ) ; 

Dolayısıyla, örneğin yöntemler için, verilen sınıf örneği içinde tutulan değer önemlidir .

Birleştirme statik bir yöntemdir. Tamam, bir sınırlayıcı ve üzerinde bir Dize dizisi verildiğinde bir Dize sonucu verir , bu nedenle Dize Sınıfı ile "bir ilgisi vardır", ancak herhangi bir Dize örneğindeki belirli bir değerle ilişkili değildir (gerçekten, örnek değerleri statik yöntemlerle kullanılamaz). Diğer bir deyişle, Join yöntemi Array Sınıfına (veya belki de daha iyisi bir StringArray Sınıfına) "yapışmış" olabilir, ancak Redmond'daki Dostlarımız bunun String sınıfıyla daha "alakalı" olduğuna karar verdiler, .

String[] array3 = { ... } 
s1 = String.Join( array3, "," ) ; 

Başka bir alternatif , birleştirme sınırlayıcısı olarak kullandığımız String [class instance] içinde tutulan değerin aşağıdaki gibi bir örnek Join yöntemine sahip olmak olabilir :

// Maybe one day ... 
String s4 = "," ; 
s1 = s4.Join( array3 ) ; 

2

staticYenilere kavramak için anahtar kelime biraz zor olabilir. Birincil amacı, bir sınıf üyesini sınıfın herhangi bir örneğine ait değil, sınıfın kendisine ait olarak tanımlamaktır.

Çok fazla ayrıntıya girmeden, C # (ve Java), tüm kod ve verilerin bir nesneye ait olması gerektiği için nesne yönelimli ideali sıkı bir şekilde zorlar ve bu nedenle kapsam, görünürlük ve ömürle sınırlıdır. Bu, gerçek dünyayı temsil eden bir nesnenin temel ilkesinin geçerli olduğu yerlerde genellikle en iyi uygulamadır. Ancak, her zaman değil; bazen ihtiyacınız olan şey, onu içeren bir nesneye referans göndermenize gerek kalmadan, kodun herhangi bir yerinden alabileceğiniz bir işlev veya değişkendir ve baktığınız veya değiştirdiğiniz verilerin tam olarak herkesin başka bir nesnenin farklı bir örneğine ait olan bir kopyasıyla ilgilenmemektedir.

Bu davranış C ve C ++ 'da bir nesnede kapsüllenmemiş "global" fonksiyon veya değişken formunda mevcuttu. Bu nedenle, bir uzlaşma olarak, C # ve Java "statik kapsam" ı destekler, üst nesne olmadan gerçekten global kod ile sınırlı kapsam örneği üyeleri arasında bir yarı noktadır.

Herhangi bir "kod üyesi" (işlev, özellik, alan) static, programın main()işlevinin ilk satırından itibaren kapsam içine girer ve main()işlev sonlanıncaya kadar bırakmaz . Basit İngilizce'de, statik bir üye vardır ve program çalıştığı sürece kullanılabilir. Ayrıca, statik üyeler, bu türün herhangi bir örneğinin üyesi olarak değil, türün kendisinin üyesi olarak çağrılarak çağrılır:

public class Foo
{
   public int MyInt {get;set;} //this is an "instance member"
   public static int MyStaticInt {get;set;} //this is a "static member"
}

...

var myFoo = new Foo();
myFoo.MyInt = 5; //valid
myFoo.MyStaticInt = 5; //invalid; MyStaticInt doesn't belong to any one Foo

Foo.MyInt = 5; //invalid; MyInt only has meaning in the context of an instance
Foo.MyStaticInt = 2; //valid

Bu, statik üyeleri, herhangi bir örneği hakkında bilgi sahibi olsun ya da olmasın, tür bilgisi olan herhangi bir kod için görünür kılar.

Sorunuzu yanıtlamak için, bir şeyi statik olarak işaretlemenin birincil yararı, tüketen kodun içerdiği nesnenin bir örneğine sahip olup olmadığına bakılmaksızın, türün kendisinin bilindiği her yerde görünür hale gelmesidir. Ayrıca hafif bir performans avantajı vardır; yöntem statik kapsamda olduğundan, yalnızca diğer statik üyelere (aynı sınıftan veya başkalarından) ve parametre olarak iletilen her şeye erişebilir. Bu nedenle, çalışma zamanının, normalde bağlama özgü durum bilgisi sağlamak için bir örnek yöntemi için gerekli olacağı için, içerilen nesnenin geçerli örneğine herhangi bir başvuruyu çözümlemesi gerekmez.

Sınıfların tamamı statik olarak da işaretlenebilir; bunu yaparak derleyiciye sınıf bildiriminin yalnızca statik üyelerden oluşacağını ve dolayısıyla somutlaştırılamayacağını söylersiniz. Bu, bellekteki bir nesnenin yalnızca bir kopyasının olmasını sağlamanın kolay bir yoludur; sınıfı ve içindeki her şeyi statik hale getirin. Bununla birlikte, bunun böyle bir ihtiyaca en iyi çözüm olması çok nadirdir. Bir veri kümesinin tam olarak bir kopyasının gerekli olduğu bir durumda, bunun yerine "singleton" genellikle savunulur; bu, kendi başına tek bir örneğe erişim sağlamak için statik erişimci ve genel olmayan bir kurucu kullanan statik olmayan bir sınıftır. Teorik olarak, bir singleton, tamamen statik bir sınıfın aynı faydalarını sağlar, ancak sınıfı örnek tabanlı, nesne yönelimli bir şekilde kullanma özelliği de eklenir.

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.