¿Por qué los métodos estáticos solo pueden usar datos estáticos?
38
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?
Porque solo existen datos estáticos desde el punto de vista de los métodos estáticos.
mouviciel
44
Compartir su investigación ayuda a todos. Cuéntanos qué has probado y por qué no satisfizo tus necesidades. Esto demuestra que te has tomado el tiempo para tratar de ayudarte a ti mismo, nos evita reiterar respuestas obvias y, sobre todo, te ayuda a obtener una respuesta más específica y relevante. También vea Cómo preguntar
mosquito
19
@gnat en este caso OP está tratando de entender la razón detrás de una decisión de diseño. ¿Qué esperas que intente en este caso?
Geek
2
@ Geek: la existencia de métodos estáticos, los datos estáticos es un problema de diseño de lenguaje. Suponiendo significados estándar, el hecho de que los métodos estáticos no puedan acceder a los datos de la instancia no lo es. La limitación está implícita en las definiciones y lo que es posible y tiene sentido, no en las debilidades de algunos diseñadores de idiomas.
Steve314
66
Parafraseando a Gertrude Stein: "No hay esto allí".
Bailarina de hipopótamos
Respuestas:
73
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):
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)
Actualizar
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:
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 nuevoFoo con los valores agregados de ambos valores pasados.
Foo foo3 =Foo.Add(foo1, foo2);// creates a new Foo with a value of 30
Expandiendo "No hay una instancia de la que tomar un valor", incluso si hay instancias, el método estático no puede saber de qué instancia tomar un valor.
Steve314
9
Esto es mucho menos complicado de explicar en lenguajes que no obligan a todo a ser parte de un objeto por defecto.
Mason Wheeler
3
@Mason Palabras verdaderas. Los lenguajes como Java imponen una noción falsa de que una función es algo que necesariamente pertenece a una clase.
KChaloux
55
Esta es una buena respuesta, pero aún no dice toda la verdad: los métodos estáticos pueden acceder a datos no estáticos. Simplemente no tienen el objeto implícito o la thisreferencia disponible. Creo que es de vital importancia entenderlo.
VENIDO del
2
@COMEFROM ¿Quiere decir con paso explícito? Puedo tomar nota de ello, si te entiendo correctamente. Supuse que estaba implícito que un método estático podría acceder a datos no estáticos pasados explícitamente, dado que cualquier función puede funcionar en los datos que se le pasan explícitamente.
KChaloux
22
Vamos a explicarlo con una muestra hipotética.
Imagina una clase simple:
classUser{User(string n){ name = n;};
string name;}
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:
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";}}
Si bien esto puede ser técnicamente un método estático que utiliza datos no estáticos, no tiene sentido. Por supuesto, puede crear una nueva instancia y acceder a ella. Pero eso no tiene nada que ver con staticness.
Bobson
2
En realidad, creo que esta es una muy buena adición para explicar el punto. Resalta el punto de que el método estático necesita una instancia de la clase antes de que pueda acceder a datos no estáticos al tiempo que proporciona una razón intuitiva por la que es así.
Ben Hocking
@Bobson Deberías leer el código y los comentarios también.
m3th0dman
@BenHocking "sí", incluso creo que es bueno decir que "la variable de instancia siempre está asociada con el objeto"
JAVA
2
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.
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.
Estoy en desacuerdo. Un método estático no puede acceder a los datos de la instancia porque se debe acceder a los datos de la instancia a través de una instancia del objeto y el método estático no está asociado con ninguna instancia dada (sino con la definición de clase).
Phill W.
Echas de menos mi punto. Si se llama desde dentro de la clase, el compilador podría pasar un puntero de instancia como lo hace cuando no es una clase estática. El problema surge si se llama desde otro lugar, lo que significa que los métodos estáticos privados podrían acceder a los datos de la instancia (aunque básicamente ignorando internamente la estática)
Loren Pechtel
Sí, el compilador / podría / pero ¿por qué debería hacerlo? Pasar dicho puntero esencialmente lo reduce a un método de instancia. Su estipulación de que solo los métodos privados pueden hacer esto es discutible: las tecnologías de reflexión hacen que / all / method sea accesible, privado o no, lo que hace que esta sea una propuesta aún más arriesgada. Nuestros amigos en Redmond han ido en la otra dirección; sus idiomas generan una advertencia si intenta llamar a un método estático contra una instancia de objeto (y no la clase en sí).
Phill W.
1
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 =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, aquí está la clase de automóvil:
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;}}
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.
classMyClass{publicstaticvoid foo(MyOtherClass object){System.out.println(object.member);}} classMyOtherClass{publicint 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.
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
new
palabra 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
static
no 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):
Actualizar
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
Foo
clase tenía otro método:Add
sigue siendo estático y no tienevalue
instancias propias, pero al ser miembro de la clase Foo puede acceder a losvalue
campos privados de las instanciasfoo1
y de las transferenciasfoo2
. En este caso, lo estamos utilizando para devolver un nuevoFoo
con los valores agregados de ambos valores pasados.fuente
this
referencia disponible. Creo que es de vital importancia entenderlo.Vamos a explicarlo con una muestra hipotética.
Imagina una clase simple:
Ahora creamos 2 instancias de esta clase:
ahora, piense: ¿y si agregamos un nuevo método estático al Usuario, por ejemplo:
y lo llamas:
¿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).
fuente
Puede usar datos de campo; considere el siguiente código de Java:
fuente
static
ness.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.
fuente
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.
fuente
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.
fuente
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.
Para completar, aquí está la clase de automóvil:
fuente
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.
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.
fuente