Entendendo a palavra-chave estática

14

Eu tenho alguma experiência em desenvolvimento com Java, Javascript e PHP.

Estou lendo o Microsoft Visual C # 2010 Step by Step, que considero um excelente livro sobre como apresentá-lo à linguagem C #.

Parece que estou tendo problemas para entender a palavra-chave estática. Pelo que entendi até agora, se uma classe é declarada estática, todos os métodos e variáveis têm que ser estáticos. O método main sempre é um método estático, portanto, na classe em que o método main existe, todas as variáveis e métodos são declarados estáticos se você tiver que chamá-los no método main. Também notei que, para chamar um método estático de outra classe, você não precisa criar um objeto que possa usar o nome da classe.

Mas qual é o objetivo real da palavra-chave estática? Quando devo declarar variáveis estáticas e métodos?

    
por Nistor Alexandru 03.09.2012 / 12:12
fonte

6 respostas

14

A palavra-chave 'static' em C # está referindo-se a algo na classe, ou a própria classe, que é compartilhada entre todas as instâncias da classe. Por exemplo, um campo marcado como estático pode ser acessado de todas as instâncias dessa classe por meio do nome da classe.

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'
    }

}

Posso dizer honestamente que nunca usei uma classe marcada como estática, com exceção da criação de métodos de extensão ( Tutorial rápido sobre métodos de extensão ).

De qualquer forma, existem padrões de design específicos para a utilização de métodos estáticos, como padrão de fábrica e singleton pattern , mas o importante a lembrar é que os métodos e construtores estáticos não lidam com nenhuma instância específica de uma classe (a menos que você passar um em), normalmente para fazer cálculos ou fazer uma comparação entre objetos. O método "Principal" ao qual você está se referindo é sempre estático, mas para vê-lo de um ponto de vista diferente, veja este artigo .

Para acompanhar isso, veja como a diferença entre métodos, campos e propriedades estáticos e instanciados é chamada.

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
}

Além disso, verifique esta postagem para saber mais olhe para classes estáticas.

    
por 04.09.2012 / 21:17
fonte
17

Aqui está a maneira de Joshua Bloch explicá-lo, que eu acho brilhante como a maioria do que ele diz (sim, eu sou um fã de Joshua Bloch :)). Isso é citado da memória.

Imagine que uma aula é o equivalente a uma cópia impressa de uma casa. A imagem então que uma casa é para o blueprint como uma instância da classe é para a classe. Você pode ter uma classe (blue-print) e várias instâncias (houses) criadas a partir dela.

Agora, o senso comum determina que a maioria das funções / comportamentos que uma casa (instância) pode ter / fazer, mesmo sendo declaradas na impressão, não pode ser usada até que uma casa real (instância) seja feita de essa cópia impressa (classe). Tipo, sua impressão azul pode conter o lugar onde a luz muda e as lâmpadas devem ir, mas você não tem como fazer esses trabalhos na cópia, você tem que realmente construir a casa para poder ligue e desligue o interruptor de luz e faça com que certas lâmpadas sejam ligadas e desligadas.

No entanto, você pode ter algum comportamento que seja aplicável diretamente à cópia impressa e que você possa usar / acessar diretamente na impressão azul sem precisar fazer uma casa real com essa impressão azul. Imagine que sua impressão azul tenha um botão que, ao pressionar, exibirá a pegada da casa contida nessa impressão azul (calculando todos os comprimentos das paredes e tal). Obviamente, você PODERIA construir uma casa primeiro, e depois medir a pegada dela, mas você pode fazer isso apenas com a cópia impressa, por isso seria mais útil ter esse comportamento implementado na cópia impressa. Esse botão incorporado de impressão azul que calcula a pegada da casa é o equivalente a ter uma função estática em uma classe.

    
por 03.09.2012 / 12:36
fonte
10

Olhar dessa maneira me ajuda:

  • Todo tipo tem uma instância estática.
  • A instância estática é criada na primeira vez que você acessa o tipo - por meio da instância estática ou criando outra instância.
  • Você pode criar quantas instâncias não estáticas desejar, mas há apenas uma instância estática.
  • Qualquer coisa dentro de uma classe declarada como estática pertence à instância estática e, portanto, não tem acesso a nenhuma outra instância criada por você. Mas as outras instâncias têm acesso à instância estática.
  • Se uma classe for declarada como estática, você não poderá criar outras instâncias, mas somente a instância estática poderá existir.
  • Você pode declarar um construtor estático para a instância estática como um construtor para uma instância normal (mas declarando-o estático).

Quanto a quando usar a palavra-chave estática:

  • Qualquer método que não precise de acesso a propriedades locais pode e provavelmente deve ser declarado como estático.
  • Classes auxiliares que não possuem nenhum estado (que deve ser raro) e que nunca serão ridicularizadas podem ser declaradas como estáticas. Se eles devem é outro assunto; use esta funcionalidade com moderação.
  • As propriedades e os campos que devem ser acessados por todas as instâncias de uma classe devem ser declarados estáticos. Mas use isso somente quando não houver outra opção.
por 03.09.2012 / 12:20
fonte
2

Explicação mais simples --- Estático = > Apenas uma cópia existirá por ambiente.

Assim, dentro de uma VM ou CLR, sempre haverá apenas uma cópia de uma classe estática, e qualquer outra classe que faça referência a ela terá que compartilhar seus métodos e dados com todas as outras classes que fizerem referência a ela.

Para uma variável estática, haverá apenas uma instância dessa variável no ambiente de tempo de execução, independentemente de quantas cópias da classe proprietária forem criadas quando fizerem referência a uma variável estática, elas farão referência à mesma parte do armazenamento. / p>     

por 18.05.2015 / 18:16
fonte
1

Membros estáticos estão associados à Classe, não a nenhuma instância dessa Classe.

Como estamos falando sobre .Net, considere a classe String , em particular os métodos Split e Join .

A divisão é um método instância . Crie uma variável String, dê a ela um valor e você pode chamar Split () nessa variável / valor e recuperar um array de "bits":

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

Assim, por exemplo, métodos, o valor mantido dentro da instância da classe dada é importante .

O Join é um método estático . OK, ele produz um resultado String quando é dado um delimitador e uma matriz String para mastigar, por isso é "algo a ver com" a classe String, mas é não associado com qualquer valor particular em qualquer instância de String (na verdade, os valores de instância não estão disponíveis para métodos estáticos).
Em outros idiomas, o método Join pode ter sido "preso" na classe Array (ou, talvez melhor, em uma classe StringArray), mas Our Friends in Redmond decidiu que era mais "relevante" para a classe String, então eles o colocaram lá .

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

Outra alternativa pode ter sido ter um método de junção instance , em que o valor mantido dentro da String [instance da classe] nos usou como o delimitador de junção, algo como:

// Maybe one day ... 
String s4 = "," ; 
s1 = s4.Join( array3 ) ; 
    
por 18.05.2015 / 13:27
fonte
1

A palavra-chave static pode ser um pouco difícil para os novatos entenderem. Seu objetivo principal é identificar um membro de classe como não pertencente a uma única instância da classe, mas sim à própria classe.

Sem entrar em muitos detalhes, C # (e Java) reforçam rigidamente o ideal orientado a objetos de que todo código e dados devem pertencer a um objeto e, portanto, são limitados em escopo, visibilidade e tempo de vida. Essa é geralmente a melhor prática, sempre que o princípio fundamental de um objeto que representa alguma coisa do mundo real se aplica. No entanto, nem sempre; às vezes, o que você precisa é de uma função ou variável que pode ser obtida de qualquer lugar no código, sem exigir que você passe uma referência a um objeto que a contenha e com a garantia de que os dados que procura ou alterando é exatamente o que todos estão lidando, e não uma cópia pertencente a uma instância diferente de um objeto.

Esse comportamento estava disponível em C e C ++ na forma da função ou variável "global", que não era encapsulada em um objeto. Assim, como um compromisso, C # e Java suportam "escopo estático", um ponto intermediário entre o código verdadeiramente global sem objeto pai e membros de instância de escopo limitado.

Qualquer "membro de código" (função, propriedade, campo) declarado como static entra no escopo da primeira linha da função main() do programa e não o deixa até que a função main() termine. Em inglês claro, existe um membro estático que pode ser usado enquanto o programa estiver em execução. Além disso, os membros estáticos são invocados chamando-os como membros do próprio tipo, não membros de nenhuma instância desse tipo:

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

Isso torna os membros estáticos visíveis para qualquer código que tenha conhecimento do tipo, quer eles saibam ou não sobre uma única instância dele.

Para responder à sua pergunta, o principal benefício de marcar algo como estático é que ele fica visível onde quer que o tipo seja conhecido, independentemente de o código consumidor ter ou poder obter uma instância do objeto contido. Há também um benefício de desempenho ligeiro ; Como o método está no escopo estático, ele só pode acessar outros membros estáticos (da mesma classe ou outros) e o que for passado como parâmetro. Portanto, o tempo de execução não precisa resolver nenhuma referência à instância atual do objeto contido, como normalmente seria necessário para um método de instância para fornecer informações de estado específicas do contexto.

Classes inteiras também podem ser marcadas como estáticas; Ao fazer isso, você diz ao compilador que a declaração de classe consistirá apenas de membros estáticos e, portanto, não poderá ser instanciada. Essa é uma maneira fácil de garantir que haja uma, e apenas uma, cópia de um objeto na memória; faça a classe e tudo nela estático. No entanto, é muito raro que esta seja a melhor solução para tal necessidade. Em uma situação em que exatamente uma cópia de um conjunto de dados é necessária, o "singleton" normalmente é defendido; essa é uma classe não estática, que usa um acessador estático e um construtor não público para fornecer acesso a uma única instância de si mesmo. Teoricamente, um singleton fornece os mesmos benefícios de uma classe totalmente estática, mas com a capacidade adicional de usar a classe de uma maneira orientada a objetos e baseada em instância.

    
por 17.11.2014 / 21:57
fonte