Porque apenas dados estáticos existem do ponto de vista dos métodos estáticos.
Mouviciel 11/09/13
4
Compartilhar sua pesquisa ajuda a todos. Conte-nos o que você tentou e por que ele não atendeu às suas necessidades. Isso demonstra que você reservou um tempo para tentar ajudar a si mesmo, evita reiterar respostas óbvias e, acima de tudo, ajuda a obter uma resposta mais específica e relevante. Veja também How to Ask
gnat
19
@gnat neste caso, o OP está tentando entender o motivo por trás de uma decisão de design. O que você espera que ele tente neste caso?
113913 Geek
2
@ Geek - a existência de métodos estáticos, dados estáticos é uma questão de design de linguagem. Assumindo significados padrão, o fato de que métodos estáticos não podem acessar dados da instância não é. A limitação está implícita nas definições e no que é possível e faz sentido, e não por alguns fracassos de designers de linguagem.
Steve314
6
Parafraseando Gertrude Stein: "Não há isso lá".
Hippo-dancer
Respostas:
73
Na maioria das linguagens OO, quando você define um método dentro de uma classe, ele se torna um Método de Instância . Ao criar uma nova instância dessa classe, por meio da newpalavra - chave, você inicializa um novo conjunto de dados exclusivo para essa instância. Os métodos pertencentes a essa instância podem trabalhar com os dados que você definiu nela.
Os métodos estáticos , por outro lado, ignoram as instâncias de classe individuais. O método estático é semelhante a uma função livre em C ou C ++. Não está vinculado a uma instanciação específica da classe. É por isso que eles não podem acessar os valores da instância. Não há nenhum exemplo para obter um valor!
Dados estáticos é semelhante a um método estático. Um valor declarado staticnão possui instância associada. Existe para todas as instâncias e é declarado apenas em um único local na memória. Se alguma vez for alterado, será alterado para todas as instâncias dessa classe.
Um método estático pode acessar dados estáticos porque ambos existem independentemente de instâncias específicas de uma classe.
Pode ajudar a ver como você chama um método estático, comparado a um método de instância. Digamos que tivemos a seguinte classe (usando pseudocódigo semelhante ao Java):
classFoo{// This static value belongs to the class Foopublicstaticfinal string name ="Foo";// This non-static value will be unique for every instanceprivateint value;publicFoo(int value){this.value = value;}publicvoid sayValue(){
println("Instance Value: "+ value);}publicstaticvoid sayName(){
println("Static Value: "+ name);}}Foo foo1 =newFoo(10);Foo foo2 =newFoo(20);
foo1.sayValue();// Prints "Instance Value: 10" - called on foo1
foo2.sayValue();// Prints "Instance Value: 20" - called on foo2Foo.sayName();// Prints "Static Value: Foo" - called on Foo (not foo1 or foo2)
Atualizar
Como COME FROM aponta nos comentários, um método estático é capaz de trabalhar com dados não estáticos, mas deve ser passado explicitamente. Vamos supor que a Fooclasse tenha outro método:
Addainda é estático e não possui valueinstâncias próprias, mas, sendo um membro da classe Foo, pode acessar os valuecampos particulares das entradas foo1e foo2instâncias. Nesse caso, estamos usando-o para retornar um novoFoo com os valores adicionados dos dois valores passados.
Foo foo3 =Foo.Add(foo1, foo2);// creates a new Foo with a value of 30
Expandindo em "Não há instância para a qual obter um valor" - mesmo se houver instâncias, o método estático não pode saber de qual instância obter um valor.
Steve314
9
Isso é muito menos complicado de explicar em linguagens que não forçam tudo a fazer parte de um objeto por padrão.
Mason Wheeler
3
@Mason Palavras verdadeiras. Linguagens como o Java meio que impõem uma noção falsa de que uma função é algo que necessariamente pertence a uma classe.
KChaloux
5
Essa é uma boa resposta, mas ainda não diz a verdade: métodos estáticos podem acessar dados não estáticos. Eles simplesmente não têm o objeto implícito ou this-referência disponível. Eu acho que isso é de vital importância para entender.
Vem
2
@COMEFROM Você quer dizer com passagem explícita? Posso fazer uma anotação, se estiver entendendo corretamente. Supus que estava implícito que um método estático poderia acessar dados não estáticos explicitamente transmitidos, uma vez que qualquer função pode funcionar com dados explicitamente transmitidos a ele.
KChaloux
22
Vamos explicar com uma amostra hipotética.
Imagine uma classe simples:
classUser{User(string n){ name = n;};
string name;}
Agora, pense - e se adicionarmos um novo método estático ao Usuário, por exemplo:
static string GetName();
e você chama:
string x =User::GetName()
o que x conteria? "Jim", "Bones", ou algo mais?
O problema é que um método estático é um método único, definido na classe, não nos objetos. Como resultado, você não sabe a qual objeto ele pode se aplicar. É por isso que é uma coisa especial. É melhor pensar em métodos estáticos como coisas individuais, como funções em C, por exemplo. O fato de linguagens como Java contê-las dentro de classes é principalmente um problema, pois o Java não permite que exista nada fora de uma classe; portanto, funções como essa devem ser forçadas dentro de uma classe de alguma maneira (um pouco como o main () é forçado a ser também dentro de uma classe quando todo o sentido diz que deve ser uma função singular e independente).
Pode usar dados de campo; considere o seguinte código java:
classMyBean{privateString myString;staticvoid myStaticMethod(){
myString ="tada";/*not allowed; if this was possible how would
be different from a field without static?*/MyBean myBean =newMyBean();//allowed if associated with an instance
myBean.myString ="tada";}}
Embora tecnicamente esse seja um método estático usando dados não estáticos, ele não é o suficiente. Claro que você pode criar uma nova instância e acessá-la. Mas isso não tem nada a ver com staticness.
Bobson
2
Na verdade, acho que esse é um ótimo complemento para explicar o ponto. Ele destaca o ponto em que o método estático precisa de uma instância da classe antes de poder acessar dados não estáticos, fornecendo uma razão intuitiva para isso.
Ben Hocking
@ Bobson Você deve ler o código e os comentários também.
M3th0dman
@BenHocking "sim" mesmo eu acho que é bom revelador ponto que "variável de instância está sempre associada a objeto"
JAVA
2
Dados não estáticos estão associados a uma instância da classe. Métodos estáticos (e dados) não estão associados a uma instância específica da classe. Não é necessário que haja uma instância de uma classe para usar métodos estáticos nela. Mesmo que houvesse instância (s), não haveria como o Java garantir que você esteja operando na instância que espera ao chamar um método estático. Portanto, métodos estáticos não podem ter acesso a dados não estáticos.
Do ponto de vista técnico, um método estático chamado de dentro de um objeto seria capaz de ver os campos da instância. Eu suspeito fortemente que foi isso que causou a pergunta em primeiro lugar.
O problema é que os métodos podem ser chamados de fora do objeto. Nesse ponto, não há dados da instância para fornecê-los - e, portanto, não há como o compilador resolver o código. Como permitir dados da instância causou uma contradição, não devemos permitir dados da instância.
Discordo. Um método estático não pode acessar os dados da instância porque os dados da instância devem ser acessados por meio de uma instância do objeto e o método estático não está associado a nenhuma instância (mas à definição da classe).
Phill W.
Você sente falta do meu ponto. Se for chamado de dentro da classe, o compilador pode passar um ponteiro de instância como acontece quando não é uma classe estática. O problema surge se ele é chamado de outros lugares - (. Ainda que por internamente basicamente ignorando a estática) o que significa que métodos estáticos privados poderiam acessar dados de instância
Loren Pechtel
Sim, o compilador / poderia / mas por que deveria? Passar esse ponteiro essencialmente o reduz a um método de instância. Sua estipulação de que apenas métodos privados podem fazer isso é discutível - as tecnologias de reflexão tornam / todos / os métodos acessíveis - privados ou não - tornando essa proposta ainda mais arriscada. Nossos amigos em Redmond foram na outra direção; os idiomas deles emitem um aviso se você tentar chamar um método estático contra uma instância do objeto (e não a própria classe).
Phill W.
1
Pense nisso como métodos estáticos que vivem em uma dimensão não orientada a objetos.
Na "dimensão orientada a objetos", uma classe pode gerar múltiplos egos (instâncias), cada ego tem consciência de si mesmo através de seu estado.
No plano, sem dimensão OO, uma classe não percebe seus egos vivendo na dimensão OO. O mundo deles é plano e processual, quase como se o OOP ainda não tivesse sido inventado, e como se a classe fosse um pequeno programa processual, e os dados estáticos fossem apenas variáveis globais.
Acho que a maneira mais fácil de explicar isso é olhar para algum código e depois considerar quais resultados esperaríamos que o código produzisse.
// Create three new cars. Cars have a name attribute. Car car1 =newCar("Mazda3");Car car2 =newCar("FordFocus");Car car3 =newCar("HondaFit");// Now we would like to print the names of some cars: // First off why don't we try this: Car.printCarName();// Expected behaviour: // If we think about what we are trying to do here it doesn't// really make sense. What instance of car name should this // print? Should it print Mazda3? FordFoucs?// What is the expected behaviour? If we are going to have a// static call on car call printCarName it should probably do// something like print all car names or a random car name or// throw an error. //Now lets try this instead: Car.printCarName(car1);// Expected Behaviour: // Luckily the expected behaviour is very clear here. This// should print Mazda3. This works as expected. // Finally lets try this:
car1.printMyName();// Expected Behaviour:// Same as previous example, however this is the *right* way// to do it.
Para completar, aqui está a classe do carro:
publicclassCar{publicString name;publicCar(String name){this.name = name;}publicstatic printCarName(){
print "Not sure what to do here... Don't know which car you are talking about.";}publicstatic printCarName(Car c){
print c.name;}public/*NOT static*/ printMyName(){
print this.name;}}
As outras respostas praticamente dizem tudo, no entanto, há alguns "detalhes" que gostaria de acrescentar.
Os métodos estáticos (digamos aqueles em Java) simplesmente não têm um objeto implícito associado a eles (acessível por this) cujos membros você pode acessar geralmente diretamente pelo nome.
Isso não significa que eles não podem acessar dados não estáticos.
classMyClass{publicstaticvoid foo(MyOtherClass object){System.out.println(object.member);}} classMyOtherClass{publicint member =10;}
Sei que isso é apenas um detalhe, mas achei sua pergunta estranha quando a li. "Pode usar apenas dados estáticos" é muito restritivo.
A propósito, eu não testei o código, apenas o escrevi aqui para exemplificar o que estava dizendo.
Respostas:
Na maioria das linguagens OO, quando você define um método dentro de uma classe, ele se torna um Método de Instância . Ao criar uma nova instância dessa classe, por meio da
new
palavra - chave, você inicializa um novo conjunto de dados exclusivo para essa instância. Os métodos pertencentes a essa instância podem trabalhar com os dados que você definiu nela.Os métodos estáticos , por outro lado, ignoram as instâncias de classe individuais. O método estático é semelhante a uma função livre em C ou C ++. Não está vinculado a uma instanciação específica da classe. É por isso que eles não podem acessar os valores da instância. Não há nenhum exemplo para obter um valor!
Dados estáticos é semelhante a um método estático. Um valor declarado
static
não possui instância associada. Existe para todas as instâncias e é declarado apenas em um único local na memória. Se alguma vez for alterado, será alterado para todas as instâncias dessa classe.Um método estático pode acessar dados estáticos porque ambos existem independentemente de instâncias específicas de uma classe.
Pode ajudar a ver como você chama um método estático, comparado a um método de instância. Digamos que tivemos a seguinte classe (usando pseudocódigo semelhante ao Java):
Atualizar
Como COME FROM aponta nos comentários, um método estático é capaz de trabalhar com dados não estáticos, mas deve ser passado explicitamente. Vamos supor que a
Foo
classe tenha outro método:Add
ainda é estático e não possuivalue
instâncias próprias, mas, sendo um membro da classe Foo, pode acessar osvalue
campos particulares das entradasfoo1
efoo2
instâncias. Nesse caso, estamos usando-o para retornar um novoFoo
com os valores adicionados dos dois valores passados.fonte
this
-referência disponível. Eu acho que isso é de vital importância para entender.Vamos explicar com uma amostra hipotética.
Imagine uma classe simples:
Agora criamos 2 instâncias dessa classe:
Agora, pense - e se adicionarmos um novo método estático ao Usuário, por exemplo:
e você chama:
o que x conteria? "Jim", "Bones", ou algo mais?
O problema é que um método estático é um método único, definido na classe, não nos objetos. Como resultado, você não sabe a qual objeto ele pode se aplicar. É por isso que é uma coisa especial. É melhor pensar em métodos estáticos como coisas individuais, como funções em C, por exemplo. O fato de linguagens como Java contê-las dentro de classes é principalmente um problema, pois o Java não permite que exista nada fora de uma classe; portanto, funções como essa devem ser forçadas dentro de uma classe de alguma maneira (um pouco como o main () é forçado a ser também dentro de uma classe quando todo o sentido diz que deve ser uma função singular e independente).
fonte
Pode usar dados de campo; considere o seguinte código java:
fonte
static
ness.Dados não estáticos estão associados a uma instância da classe. Métodos estáticos (e dados) não estão associados a uma instância específica da classe. Não é necessário que haja uma instância de uma classe para usar métodos estáticos nela. Mesmo que houvesse instância (s), não haveria como o Java garantir que você esteja operando na instância que espera ao chamar um método estático. Portanto, métodos estáticos não podem ter acesso a dados não estáticos.
fonte
Eu acho que a questão aqui é de entendimento.
Do ponto de vista técnico, um método estático chamado de dentro de um objeto seria capaz de ver os campos da instância. Eu suspeito fortemente que foi isso que causou a pergunta em primeiro lugar.
O problema é que os métodos podem ser chamados de fora do objeto. Nesse ponto, não há dados da instância para fornecê-los - e, portanto, não há como o compilador resolver o código. Como permitir dados da instância causou uma contradição, não devemos permitir dados da instância.
fonte
Pense nisso como métodos estáticos que vivem em uma dimensão não orientada a objetos.
Na "dimensão orientada a objetos", uma classe pode gerar múltiplos egos (instâncias), cada ego tem consciência de si mesmo através de seu estado.
No plano, sem dimensão OO, uma classe não percebe seus egos vivendo na dimensão OO. O mundo deles é plano e processual, quase como se o OOP ainda não tivesse sido inventado, e como se a classe fosse um pequeno programa processual, e os dados estáticos fossem apenas variáveis globais.
fonte
Acho que a maneira mais fácil de explicar isso é olhar para algum código e depois considerar quais resultados esperaríamos que o código produzisse.
Para completar, aqui está a classe do carro:
fonte
As outras respostas praticamente dizem tudo, no entanto, há alguns "detalhes" que gostaria de acrescentar.
Os métodos estáticos (digamos aqueles em Java) simplesmente não têm um objeto implícito associado a eles (acessível por
this
) cujos membros você pode acessar geralmente diretamente pelo nome.Isso não significa que eles não podem acessar dados não estáticos.
Sei que isso é apenas um detalhe, mas achei sua pergunta estranha quando a li. "Pode usar apenas dados estáticos" é muito restritivo.
A propósito, eu não testei o código, apenas o escrevi aqui para exemplificar o que estava dizendo.
fonte