Não entendo por que um método estático não pode usar dados não estáticos. Alguém pode explicar quais são os problemas e por que não podemos fazê-lo?
Não entendo por que um método estático não pode usar dados não estáticos. Alguém pode explicar quais são os problemas e por que não podemos fazê-lo?
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):
class Foo {
// This static value belongs to the class Foo
public static final string name = "Foo";
// This non-static value will be unique for every instance
private int value;
public Foo(int value) {
this.value = value;
}
public void sayValue() {
println("Instance Value: " + value);
}
public static void sayName() {
println("Static Value: " + name);
}
}
Foo foo1 = new Foo(10);
Foo foo2 = new Foo(20);
foo1.sayValue(); // Prints "Instance Value: 10" - called on foo1
foo2.sayValue(); // Prints "Instance Value: 20" - called on foo2
Foo.sayName(); // Prints "Static Value: Foo" - called on Foo (not foo1 or foo2)
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:
public static Foo Add(Foo foo1, Foo foo2) {
return new Foo(foo1.value + foo2.value);
}
Add
ainda é estático e não possui value
instâncias próprias, mas, sendo um membro da classe Foo, pode acessar os value
campos particulares das entradas foo1
e foo2
instâncias. Nesse caso, estamos usando-o para retornar um novo Foo
com os valores adicionados dos dois valores passados.
Foo foo3 = Foo.Add(foo1, foo2); // creates a new Foo with a value of 30
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:
class User
{
User(string n) { name = n; };
string name;
}
Agora criamos 2 instâncias dessa classe:
User Bones = new User("Bones");
User Jim = new User("Jim");
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:
class MyBean {
private String myString;
static void myStaticMethod() {
myString = "tada";/*not allowed; if this was possible how would
be different from a field without static?*/
MyBean myBean = new MyBean();//allowed if associated with an instance
myBean.myString = "tada";
}
}
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.
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.
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 = new Car("Mazda3");
Car car2 = new Car("FordFocus");
Car car3 = new Car("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:
public class Car{
public String name;
public Car(String name){
this.name = name;
}
public static printCarName(){
print "Not sure what to do here... Don't know which car you are talking about.";
}
public static 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.
class MyClass {
public static void foo(MyOtherClass object) {
System.out.println(object.member);
}
}
class MyOtherClass {
public int 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.