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

38

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?

JAVA
la source
11
Parce que seules les données statiques existent du point de vue des méthodes statiques.
mouviciel
4
Partager vos recherches aide tout le monde. Dites-nous ce que vous avez essayé et pourquoi il ne répondait pas à vos besoins. Cela montre que vous avez pris le temps d'essayer de vous aider, que cela nous évite de réitérer des réponses évidentes et, surtout, que cela vous aide à obtenir une réponse plus précise et plus pertinente. Voir également Comment poser des questions
Gnat
19
@gnat dans ce cas, OP tente de comprendre la raison d'une décision de conception. Qu'attendez-vous de lui dans ce cas?
Geek
2
@ Geek - l'existence de méthodes statiques, les données statiques est un problème de conception de langage. En supposant des significations standard, le fait que les méthodes statiques ne puissent pas accéder aux données d'instance ne l'est pas. La limitation est impliquée par les définitions et par ce qui est possible et logique, et non par les faiblesses de certains concepteurs de langage.
Steve314
6
Pour paraphraser Gertrude Stein: "Il n'y a pas cela ici."
hippo-danseuse

Réponses:

73

Dans la plupart des langages OO, lorsque vous définissez une méthode dans une classe, celle-ci devient une méthode d'instance . Lorsque vous créez une nouvelle instance de cette classe, via le newmot - clé, vous initialisez un nouvel ensemble de données unique pour cette instance uniquement. Les méthodes appartenant à cette instance peuvent ensuite utiliser les données que vous avez définies dessus.

Les méthodes statiques , en revanche, ignorent les instances de classe individuelles. La méthode statique est similaire à une fonction libre en C ou C ++. Cela 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'exemple à prendre une valeur de!

Les données statiques sont similaires à une méthode statique. Une valeur déclarée staticn'a pas d'instance associée. Il existe pour chaque instance et n'est déclaré qu'en un seul endroit en mémoire. Si cela change un jour, cela changera pour chaque instance de cette classe.

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

Il peut être utile de regarder comment vous appelez une méthode statique par rapport à une méthode d'instance. Disons que nous avions la classe suivante (utilisant un pseudocode semblable à 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 transmise explicitement. Supposons que la Fooclasse utilise une autre méthode:

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

Addest toujours statique et n'a pas d' valueinstance propre, mais étant membre de la classe Foo, il peut accéder aux valuechamps privés des occurrences foo1et foo2instances passées . Dans ce cas, nous l'utilisons pour renvoyer une nouvelle 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
KChaloux
la source
30
Développement sur "Il n'y a pas d'instance pour prendre une valeur" - même s'il existe des instances, la méthode statique ne peut pas savoir à quelle instance prendre une valeur.
Steve314
9
C’est beaucoup moins compliqué à expliquer dans des langages qui ne forcent pas tout à faire partie d’un objet par défaut.
Mason Wheeler le
3
@Mason Vrais mots. Les langages comme Java imposent en quelque sorte une fausse notion selon laquelle une fonction est quelque chose qui appartient nécessairement à une classe.
KChaloux
5
C'est une bonne réponse, mais elle ne dit toujours pas la vérité: les méthodes statiques peuvent accéder à des données non statiques. Ils n'ont tout simplement pas d'objet ou de thisréférence implicite disponible. Je pense qu'il est extrêmement important de comprendre.
VENEZ DU
2
@COMEFROM Vous voulez dire par un passage explicite? Je peux en prendre note si je vous comprends bien. J'ai supposé que cela impliquait qu'une méthode statique pouvait accéder à des données non statiques explicitement passées, étant donné que toute fonction peut travailler sur des données explicitement transmises.
KChaloux
22

Permet de l'expliquer avec un échantillon hypothétique.

Imaginez un cours simple:

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

Maintenant, nous créons 2 instances de cette classe:

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

Maintenant, réfléchissez - et si nous ajoutions une nouvelle méthode statique à User, par exemple:

static string GetName();

et vous l'appelez:

string x = User::GetName()

Que contiendrait 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 les objets. Par conséquent, vous ne savez pas à quel objet il peut s’appliquer. C'est pourquoi c'est une chose spéciale. Il est préférable de considérer les méthodes statiques comme des choses individuelles, comme des fonctions en C par exemple. Le fait que des langages comme Java les contiennent dans les classes est principalement un problème, car Java n'autorise rien d'existant en dehors d'une classe. Par conséquent, des fonctions comme celle-ci doivent être forcées dans une classe d'une manière ou d'une autre à l’intérieur d’une classe aussi, quand tout le monde dit que ce devrait être une fonction singulière et autonome).

gbjbaanb
la source
3

Il peut utiliser des données de terrain. considérez le code java suivant:

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";
    }
}
m3th0dman
la source
Bien que cela puisse techniquement être une méthode statique utilisant des données non statiques, elle passe à côté de l'essentiel. Bien sûr, vous pouvez créer une nouvelle instance et y accéder. Mais cela n’a rien à voir avec la staticnessité.
Bobson
2
En fait, je pense que c’est un très bon complément pour expliquer ce point. Cela met en évidence le fait que la méthode statique a besoin d'une instance de la classe avant de pouvoir accéder à des données non statiques, tout en fournissant une raison intuitive à cela.
Ben Hocking
@Bobson Vous devriez également lire le code et les commentaires.
m3th0dman
@BenHocking "oui" même si je pense que c'est un bon point de dire que "la variable d'instance est toujours associée à l'objet"
JAVA
2

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'une instance de classe utilise 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 opérez sur l'instance que vous attendez lorsque vous appelez une méthode statique. Par conséquent, les méthodes statiques ne peuvent pas accéder à des données non statiques.

smp7d
la source
2

Je pense que le problème ici est celui 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 posé 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. Comme autoriser les données d'instance a créé une contradiction, nous ne devons pas autoriser les données d'instance.

Loren Pechtel
la source
Je ne suis pas d'accord. Une méthode statique ne peut pas accéder aux données d'instance car les données d'instance doivent être accessibles via une instance de l'objet et la méthode statique n'est associée à aucune instance donnée (mais à la définition de la classe).
Phill W.
Vous manquez mon point. S'il est appelé depuis la classe, le compilateur peut transmettre un pointeur d'instance comme il le fait lorsqu'il ne s'agit pas d'une classe statique. Le problème vient du fait qu'il appelle ailleurs - ce qui signifie que les méthodes statiques privées peuvent accéder aux données d'instance (même en ignorant fondamentalement en interne le
paramètre
Oui, le compilateur / pourrait / mais pourquoi le ferait-il? Passer un tel pointeur le réduit essentiellement à une méthode d'instance. Votre stipulation selon laquelle seules les méthodes privées peuvent le faire est sans objet. Les technologies de réflexion rendent toutes les méthodes accessibles, qu'elles soient privées ou non, ce qui en fait une proposition encore plus risquée. Nos amis à Redmond sont allés dans la direction opposée; leurs langues déclenchent un avertissement si vous essayez d'appeler une méthode statique sur une instance d'objet (et non sur la classe elle-même).
Phill W.
1

Considérez-le comme une méthode statique vivant dans une dimension non orientée objet.

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

Dans la dimension plate, non-OO, une classe ignore que son ego vit dans la dimension OO. Leur monde est plat et procédural, presque comme si la POO n'avait pas encore été inventée, et comme si la classe était un petit programme procédural, et que les données statiques n'étaient que des variables globales.

Tulains Córdova
la source
1

Je pense que la meilleure façon d’expliquer cela est d’examiner du code, puis de déterminer les résultats attendus 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;
    }

}
soixantefootersdude
la source
Comment cela répond-il à la question posée?
Gnat
1
@gnat Mis à jour avec des commentaires pour clarifier.
Sixtyfootersdude
1

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

Les méthodes statiques (disons celles en Java) n’ont tout simplement pas d’objet implicite associé (accessible via this ) dont les membres sont généralement accessibles directement par leur nom.

Cela ne signifie pas qu'ils ne peuvent pas accéder à des 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 quand je l'ai lue. "Peut utiliser uniquement des données statiques" est trop restrictif.

En passant, je n'ai pas testé le code, je l'ai simplement écrit ici pour illustrer ce que je disais.

Pedro Henrique A. Oliveira
la source