No entiendo por qué un método estático no puede usar datos no estáticos. ¿Alguien puede explicar cuáles son los problemas y por qué no podemos hacerlo?
No entiendo por qué un método estático no puede usar datos no estáticos. ¿Alguien puede explicar cuáles son los problemas y por qué no podemos hacerlo?
Respuestas:
En la mayoría de los lenguajes OO, cuando define un método dentro de una clase, se convierte en un Método de instancia . Cuando crea una nueva instancia de esa clase, a través de la newpalabra clave, inicializa un nuevo conjunto de datos exclusivo de esa instancia. Los métodos que pertenecen a esa instancia pueden funcionar con los datos que definió en ella.
Los métodos estáticos , por el contrario, ignoran las instancias de clases individuales. El método estático es similar a una función libre en C o C ++. No está vinculado a una instanciación específica de la clase. Es por eso que no pueden acceder a los valores de instancia. ¡No hay una instancia para tomar un valor!
Los datos estáticos son similares a un método estático. Un valor que se declara staticno tiene una instancia asociada. Existe para cada instancia, y solo se declara en un solo lugar en la memoria. Si alguna vez se cambia, cambiará para cada instancia de esa clase.
Un método estático puede acceder a datos estáticos porque ambos existen independientemente de instancias específicas de una clase.
Puede ser útil observar cómo invocar un método estático, en comparación con un método de instancia. Digamos que teníamos la siguiente clase (usando pseudocódigo similar a 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 señala en los comentarios, un método estático es capaz de trabajar con datos no estáticos, pero debe pasarse explícitamente. Asumamos que la Fooclase tenía otro método:
public static Foo Add(Foo foo1, Foo foo2) {
return new Foo(foo1.value + foo2.value);
}
Addsigue siendo estático y no tiene valueinstancias propias, pero al ser miembro de la clase Foo puede acceder a los valuecampos privados de las instancias foo1y de las transferencias foo2. En este caso, lo estamos utilizando para devolver un nuevo Foo con los valores agregados de ambos valores pasados.
Foo foo3 = Foo.Add(foo1, foo2); // creates a new Foo with a value of 30
thisreferencia disponible. Creo que es de vital importancia entenderlo.
Vamos a explicarlo con una muestra hipotética.
Imagina una clase simple:
class User
{
User(string n) { name = n; };
string name;
}
Ahora creamos 2 instancias de esta clase:
User Bones = new User("Bones");
User Jim = new User("Jim");
ahora, piense: ¿y si agregamos un nuevo método estático al Usuario, por ejemplo:
static string GetName();
y lo llamas:
string x = User::GetName()
¿Qué contendría x? "Jim", "Bones", o algo más?
El problema es que un método estático es un método único, definido en la clase, no en los objetos. Como resultado, no sabe a qué objeto podría aplicarse. Por eso es algo especial. Es mejor pensar en los métodos estáticos como cosas individuales, como funciones en C, por ejemplo. Que los lenguajes como Java los contengan dentro de las clases es principalmente un problema con Java que no permite que exista nada fuera de una clase, por lo que funciones como esta deben forzarse dentro de una clase de alguna manera (un poco como cómo se obliga a main () dentro de una clase también cuando todo sentido dice que debería ser una función singular e independiente).
Puede usar datos de campo; considere el siguiente código de 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";
}
}
staticness.
Los datos no estáticos están asociados a una instancia de la clase. Los métodos estáticos (y los datos) no están asociados a una instancia particular de la clase. No es necesario que haya una instancia de una clase para usar métodos estáticos en ella. Incluso si hubiera instancias, Java no garantizaría que está operando en la instancia que espera cuando llama a un método estático. Por lo tanto, los métodos estáticos no pueden tener acceso a datos no estáticos.
Creo que el problema aquí es de comprensión.
Desde un punto de vista técnico, un método estático llamado desde un objeto sería bastante capaz de ver los campos de instancia. Sospecho firmemente que esto es lo que causó la pregunta en primer lugar.
El problema es que los métodos pueden llamarse desde fuera del objeto. En ese momento no hay datos de instancia para proporcionarlos, y por lo tanto no hay forma de que el compilador resuelva el código. Dado que permitir datos de instancia causó una contradicción, no debemos permitir datos de instancia.
Piense en ello como métodos estáticos que viven en una dimensión no orientada a objetos.
En la "dimensión orientada a objetos", una clase puede generar múltiples egos (instancias), cada ego tiene conciencia de sí mismo a través de su estado.
En la dimensión plana, no OO, una clase es ajena a sus egos que viven en la dimensión OO. Su mundo es plano y procesal, casi como si la POO aún no se hubiera inventado, y como si la clase fuera un pequeño programa procesal y los datos estáticos fueran solo variables globales.
Creo que la forma más fácil de explicar esto es mirar algún código y luego considerar qué resultados esperaríamos que produzca el código.
// 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, aquí está la clase de automóvil:
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;
}
}
Las otras respuestas lo dicen todo, sin embargo, hay algunos "detalles" que me gustaría agregar.
Los métodos estáticos (digamos aquellos en Java) simplemente no tienen un objeto implícito asociado a ellos (accesible a través this) a cuyos miembros se puede acceder generalmente directamente por nombre.
Eso no significa que no puedan acceder a datos no estáticos.
class MyClass {
public static void foo(MyOtherClass object) {
System.out.println(object.member);
}
}
class MyOtherClass {
public int member = 10;
}
Sé que esto es solo un detalle, pero encontré tu pregunta extraña cuando la leí. "Solo se pueden usar datos estáticos" es demasiado restrictivo.
Por cierto, no probé el código, simplemente lo escribí aquí para ejemplificar lo que estaba diciendo.