Static members belong to the type, not the instance
Static members are best seen as belonging to the type rather than the instance. If you're inside a class, it can be harder to see:
class Animal
{
static int moveSpeed = 4;
int currentLocation = 10;
void Walk()
{
// Can you tell which variable is static without looking above?
currentLocation += moveSpeed;
}
}
But it's easier to see in an external scope where the member needs to be called:
void Foo()
{
var animal = new Animal();
var x1 = animal.moveSpeed; // Invalid - .moveSpeed belongs to the type, not a specific animal
var x2 = animal.currentLocation; // Valid
var x3 = Animal.moveSpeed; // Valid
var x4 = Animal.currentLocation; // Invalid - the type Animal doesn't have some common value for currentLocation
}
See static
members through the compiler's eyes
In languages like C#/Java, the compiler makes all methods static
during the compilation process. Instance methods get an extra argument added to their method signature that specifies this
:
class Animal
{
// In source code, as before:
void Walk()
{
currentLocation += moveSpeed;
}
// More explicit source code:
void Walk()
{
this.currentLocation += Animal.moveSpeed;
}
// How the compiler sees it:
static void Walk(Animal this)
{
this.currentLocation += Animal.moveSpeed;
}
}
Analogies
Since static
methods are those that don't vary with an instance, you can compare them to personal qualities about people vs. impersonal qualities.
For example, when students hand in a math test, if the answer to a problem is $5$, then that's the correct answer for all students. But, Bob should write "Bob" on his exam, while Sally should write "Sally" on her exam - that varies with the instance of the student.
static
relativity
Analogies can get tricky because static
-ness is relative. This isn't easy to reproduce in simple type systems like used in Java/C#, but it's apparent in languages with more meta-programming features, e.g. Ruby, where a type is itself an instance of another type.
For an analogy, consider a class Dog
. You might say that all Dog
's have .Legs = 4;
, but that they can have differing .Weights
. From this perspective, .Legs
is static.
But, Dog
can itself be an instance of a class, Animal
. From the perspective of Animal
, .Legs
isn't static, but rather varies with the instances of Animal
- and the instance called Dog
just happens to have .Legs=4;
, but the instance called Human
has .Legs=2;
.
Static relativity won't make sense if students are just learning Java/C#-like type systems, but some students might ask questions that bring it up anyway. For example, if you give .Legs
as an example, students might ask how to handle a more general type where .Legs
can vary - this can be explained through a meta-class structure.
static
keyword was re-used in C++ for this usage, to avoid introducing another keyword. How did you explainvoid
,public
,main
? All of these have no good meaning in lesson1, and can only be explained about ½way through the course. In Eiffel it does not have these words, there is no main, there are reasonable defaults of access, if you don't return a value than don't declare a return type, and there is no such thing as static, you don't need it (the only use for it is once methods, eiffel has these. All other uses are harmful). $\endgroup$