web-dev-qa-db-fra.com

Pourquoi les méthodes statiques peuvent-elles uniquement utiliser des données statiques?

Je ne comprends pas pourquoi une méthode statique ne peut pas utiliser de données non statiques. Quelqu'un peut-il expliquer quels sont les problèmes et pourquoi nous ne pouvons pas le faire?

38
JAVA

Dans la plupart des langues OO, lorsque vous définissez une méthode à l'intérieur d'une classe, elle devient une méthode d'instance. Lorsque vous créez une nouvelle instance de cette classe, via le mot clé new, vous initialisez un nouvel ensemble de données unique à cette instance. Les méthodes appartenant à cette instance peuvent ensuite fonctionner avec les données que vous défini dessus.

Méthodes statiques, en revanche, ignorent les instances de classe individuelles. La méthode statique est similaire à une fonction libre en C ou C++. Il n'est pas lié à une instanciation spécifique de la classe. C'est pourquoi ils ne peuvent pas accéder aux valeurs d'instance. Il n'y a pas d'instance pour prendre une valeur!

Données statiques est similaire à une méthode statique. Une valeur déclarée static n'a pas d'instance associée. Il existe pour chaque instance, et n'est déclaré qu'à un seul endroit de la mémoire. Si jamais il est changé, il changera pour chaque instance de cette classe.

Un méthode statique peut accéder à données statiques car ils existent tous les deux indépendamment des instances spécifiques d'une classe.

Il peut être utile de voir comment vous appelez une méthode statique, par rapport à une méthode d'instance. Disons que nous avions la classe suivante (en utilisant un pseudocode de type 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)

Mise à jour

Comme COME FROM le souligne dans les commentaires, une méthode statique est capable de travailler avec des données non statiques, mais elle doit être passé explicitement. Supposons que la classe Foo ait une autre méthode:

public static Foo Add(Foo foo1, Foo foo2) {
    return new Foo(foo1.value + foo2.value);
}

Add est toujours statique et n'a pas d'instances value qui lui soient propres, mais en étant membre de la classe Foo, il peut accéder aux champs privés value des _ passés foo1 et foo2 instances. Dans ce cas, nous l'utilisons pour renvoyer un nouveau Foo avec les valeurs ajoutées des deux valeurs transmises.

Foo foo3 = Foo.Add(foo1, foo2); // creates a new Foo with a value of 30
73
KChaloux

Expliquons-le avec un échantillon hypothétique.

Imaginez une classe simple:

class User
{
User(string n) { name = n; };
string name;
}

Nous créons maintenant 2 instances de cette classe:

User Bones = new User("Bones");
User Jim = new User("Jim");

maintenant, pensez - et si nous ajoutons une nouvelle méthode statique à l'utilisateur, par exemple:

static string GetName();

et vous l'appelez:

string x = User::GetName()

que contient x? "Jim", "Bones", ou autre chose?

Le problème est qu'une méthode statique est une méthode unique, définie sur la classe, pas sur les objets. Par conséquent, vous ne savez pas à quel objet il pourrait s'appliquer. C'est pourquoi c'est une chose spéciale. Il vaut mieux penser aux méthodes statiques comme des choses individuelles, comme les fonctions en C par exemple. Le fait que des langages comme Java les contiennent dans des classes est principalement un problème avec Java ne permettant rien d'exister en dehors d'une classe, donc des fonctions comme celle-ci doivent être forcées à l'intérieur d'une classe d'une certaine manière (un peu comme la façon dont main () est forcé d'être à l'intérieur d'une classe aussi quand tout sens dit que cela devrait être une fonction autonome et singulière).

22
gbjbaanb

Il peut utiliser des données de terrain; considérez le code Java code:

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";
    }
}
3
m3th0dman

Je pense que la question ici est celle de la compréhension.

D'un point de vue technique, une méthode statique appelée depuis un objet serait tout à fait capable de voir les champs d'instance. Je soupçonne fortement que c'est ce qui a causé la question en premier lieu.

Le problème est que les méthodes peuvent être appelées de l'extérieur de l'objet. À ce stade, il n'y a aucune donnée d'instance à leur fournir - et donc aucun moyen pour le compilateur de résoudre le code. Étant donné que l'autorisation des données d'instance a provoqué une contradiction, nous ne devons pas autoriser les données d'instance.

2
Loren Pechtel

Les données non statiques sont associées à une instance de la classe. Les méthodes statiques (et les données) ne sont pas associées à une instance particulière de la classe. Il n'est pas nécessaire qu'il y ait une instance d'une classe pour utiliser des méthodes statiques dessus. Même s'il y avait des instances, il n'y aurait aucun moyen pour Java de garantir que vous travaillez sur l'instance que vous attendez lorsque vous appelez une méthode statique. Par conséquent, les méthodes statiques ne peuvent pas avoir accès aux données non statiques.

2
smp7d

Je pense que la façon la plus simple d'expliquer cela est de regarder du code, puis de considérer les résultats que nous attendons du code.

// 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.  

Pour être complet, voici la classe de voiture:

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

}
1
sixtyfootersdude

Les autres réponses disent à peu près tout, cependant, il y a quelques "détails" que j'aimerais ajouter.

Les méthodes statiques (par exemple celles de Java) n'ont tout simplement pas d'objet implicite qui leur est associé (accessible via this) dont vous pouvez généralement accéder directement aux membres par leur nom.

Cela ne signifie pas qu'ils ne peuvent pas accéder aux données non statiques.

class MyClass {
  public static void foo(MyOtherClass object) {
    System.out.println(object.member);
  }
}
class MyOtherClass { public int member = 10; }

Je sais que ce n'est qu'un détail, mais j'ai trouvé votre question étrange en la lisant. "Ne peut utiliser que des données statiques" est trop restrictif.

Au fait, je n'ai pas testé le code, je l'ai juste écrit ici pour illustrer ce que je disais.

Considérez-le comme des méthodes statiques vivant dans une dimension non orientée objet.

Dans la "dimension orientée objet", une classe peut engendrer de multiples egos (instances), chaque ego a conscience de lui-même via son état.

Dans la dimension plate et non OO, une classe est inconsciente de leur ego vivant dans la dimension OO. Leur monde est plat et procédural, presque comme si OOP n'avait pas encore été inventé, et comme si la classe était un petit programme procédural et que les données statiques n'étaient que des variables globales.

1
Tulains Córdova