5

Wikipedia defines virtual methods as:

In object-oriented programming, a virtual function or a virtual method is a function or method whose behavior can be overridden within an inheriting class by a function with the same signature [to provide a polymorphic behavior].

According to the definition, every non-static method in Java is by default virtual except final and private methods. The method which cannot be inherited for polymorphic behavior is not a virtual method.

Static methods in Java can never be overridden; hence, it is meaningless to declare a static method as final in Java because static methods themselves behave just like final methods. They can simply be hidden in sub classes by the methods with the same signature. It is evidently so because static methods can never have polymorphic behavior: a method which is overridden must achieve polymorphism, which is not the case with static methods.

From the preceding paragraph, an important conclusion can be driven. All the methods in C++ are by default static because no methods in C++ can behave polymorphically until and unless they are explicitly declared virtual in the super class. In contrast, all the methods in Java except final, static and private methods are by default virtual because they have polymorphic behavior by default (there's no need to explicitly declare methods as virtual in Java and, consequently, Java has no keyword like "virtual").

Now, let's demonstrate that instance variables (static too) cannot behave polymorphically from the following simple example in Java.

class Super
{
    public int a=5;
    public int show()
    {
        System.out.print("Super method called a = ");
        return a;
    }
}

final class Child extends Super
{
    public int a=6;

    @Override
    public int show()
    {
        System.out.print("Child method called a = ");
        return a;
    }
}

final public class Main
{
    public static void main(String...args)
    {
        Super s = new Child();
        Child c = new Child();

        System.out.println("s.a = "+s.a);
        System.out.println("c.a = "+c.a);        

        System.out.println(s.show());
        System.out.println(c.show());
    }
}

The output produced by the above code snippet is as follows.

s.a = 5
c.a = 6
Child method called a = 6
Child method called a = 6

In this example, both calls s.show() and c.show() made to the show() method through the variables of type Super and of type Child, respectively, invoke the show() method in the Child class. This means that the show() method in the Child class overrides the show() method in the Super class because both of them have the identical signature.

This, however, cannot be applied to the instance variable a declared in both the classes. In this case, s.a would refer to a in the Super class and display 5 and c.a would refer to a in the Child class and display 6 means that a in the Child class just hides (and doesn't override as happened to non-static methods) a in the Super class.

After this long discussion, there is only one question. Why are instance variables (and the rest too) not overridden? What were the special reasons to implement such a mechanism? Would have there been any advantages or disadvantages, if they had been overridden?

outis
  • 75,655
  • 22
  • 151
  • 221
Lion
  • 18,729
  • 22
  • 80
  • 110
  • 1
    C++ non-virtual methods are not static. they're instance methods which can't be overridden. They're similar to final methods in Java: instance methods that can't be overridden. – JB Nizet Dec 28 '11 at 11:13
  • `According to the above paragraph, an important conclusion can be driven. All the methods in C++ (also in C) are by default static because no methods in C++ can behave polymorphically until and unless they are explicitly declared virtual in the base` : a static method cannot access the object [no `this` for these methods] while a non virtual [default] function in C++ can – amit Dec 28 '11 at 11:13
  • 1
    I thing the word "overridden" is not appliable to variables. You override behavior, but not state. Variables can be accessed from the subclass, so no need to "override" (you can change its value and it has the same name). Also there's something called shadowing, so if you redeclare another variable with the same name it is another different variable at runtime. – Mister Smith Dec 28 '11 at 11:14
  • @Lion: Please use blockquotes for anything you copied from somewhere else and cite your sources. – outis Dec 28 '11 at 11:50
  • @outis:) I didn't copy anything from anywhere else. It's my study that may somewhat be incorrect somewhere as I myself have no that much experience that the language designers have. – Lion Dec 28 '11 at 11:56
  • @amt 'static' means that no specific instance of the class is required. It has nothing whatsoever to do with virtual or overriding. – user207421 Dec 28 '11 at 12:07
  • @Lion: I don't believe you. First paragraph on the Wikipedia article on [virtual functions](http://en.wikipedia.org/wiki/Virtual_function): "In object-oriented programming, a virtual function or virtual method is a function or method whose behaviour can be overridden within an inheriting class by a function with the same signature. This concept is a very important part of the polymorphism portion of object-oriented programming (OOP)." – outis Dec 28 '11 at 12:29
  • Note that the signatures don't need to be the same. They only need to be compatible according to the [Liskov Substitution Principle](http://stackoverflow.com/questions/56860/). – outis Dec 28 '11 at 12:36
  • This really belongs on programmers.SE – outis Dec 28 '11 at 12:37
  • @outis:) I understand what you say is correct but you shouldn't claim, blame and offend me that I directly copied it from the *Wikipedia article*, since it was taught to me in my collage time. It was from there. – Lion Dec 28 '11 at 14:09
  • @Lion: copying something near verbatim without attribution is called plagiarism, regardless of whether you already understood the material. I would have hoped your college professors taught you better than that. Quoting sources helps your position, because the quoted text comes from a more authoritative source. – outis Dec 28 '11 at 18:33

4 Answers4

3

I think that the purpose of overriding is changing functionality without changing the signature. This is relevant for methods only: method may have the same signature but have different behavior. Fields have only "signature" that is also limited to there type and name. They do not have behavior, so nothing can be overridden.

Other reason to inability to "override" fields is that fields are typically private (or should be private), so they are actually the gory details of the class implementation. Methods however represent the external interface of the class. This external interface should support polymorphous to make it easier to change functionality of modules without changing the relationships between modules.

AlexR
  • 114,158
  • 16
  • 130
  • 208
  • According to the Liskov Substitution Principle, the signatures don't have to be the same: the return type should be covariant (same or derived type) and arguments should be contravariant (same or basal type) in the signature of overriding methods. Similarly, the type of a field with the same name in a descendant should be covariant, so it can make sense to "override" fields. – outis Dec 28 '11 at 12:40
  • @outis: The type of a field is analogous *both* to a getter's return-type (`Number x = this.x` is analogous to `Number x = this.getX()`) *and* to a setter's parameter-type (`this.x = (Number)x` is analogous to `this.setX((Number) x)`). So it has to be invariant. (And this is true even if the field is `final`, since the superclass constructor is what will be setting it in that case.) – ruakh Nov 12 '16 at 21:55
2

There's another use of the term "static" when referring to name resolution: static resolution is when the declared type of a variable is used to resolve the name, dynamic when the type of the data stored in the variable is used. Static resolution can be done at compile time, while dynamic resolution must be done at run time. Resolving virtual members (which is a form of dynamic resolution) requires an extra level of indirection, a table lookup. Allowing "virtual" fields would incur a runtime cost.

Once static resolution for all members is done away with, there is little point in having statically typed variables. At that point, you may as well have a dynamically typed language, such as Python and the multitude of Lisp variants. When you discard static types, it no longer makes sense to try to speak of child fields not overriding (or overriding) parent fields, because there is no longer a static variable type to suggest otherwise.

class Super(object):
    a=5
    def show(self):
        print("Super method called a = ", end='')
        return self.a

class Child(Super):
    a=6
    def show(self):
        print("Child method called a = ", end='')
        return self.a

# there's no indication that 's' is supposed to be a Super...
s = Child();
c = Child();

# so it's no surprise that s.a is Child.a
print("s.a =", s.a)
# result: "s.a = 6"
print("c.a =", c.a)
# result: "c.a = 6"
print(s.show())
# result: "Child method called a = 6"
print(c.show())
# result: "Child method called a = 6"

Common lisps, it should be noted, have both type declarations and dynamic resolution.

(defgeneric show (o))

(defclass super () 
  ((a :accessor super-a
     :initform 5
     :initarg :a))
  )

(defmethod show ((o super))
  (list "Super method called a = " 
        (slot-value o 'a))
  )

(defclass child (super)
  ((a :accessor child-a
     :initform 6
     :initarg :a))
  )

(defmethod show ((o child))
  (list "Child method called a = "
        (slot-value o 'a))
  )

(defun test (s c)
  (declare (type super s))
  (declare (type child c))
  (list (list "s.a =" (slot-value s 'a))
        (list "c.a =" (slot-value c 'a))
        (show s)
        (show c)
        )
  )

(test (make-instance 'child) (make-instance 'child))
;; result: '(("s.a =" 6) ("c.a =" 6) ("Child method called a = " 6) ("Child method called a = " 6))

In pure OOP (according to some), objects shouldn't have public fields, only public members, so that fields are resolved statically isn't an issue.

All the methods in C++ (also in C) are by default static [...]

No, because static means more than "can't be overridden" in Java, and don't mean that at all in C++. In both, the essential property of static methods is they are class methods, accessed via a class, rather than an instance (though Java allows them to be accessed by either).

outis
  • 75,655
  • 22
  • 151
  • 221
2

Look at the C# world. The use of public instance variables is strictly discouraged - see StyleCop. The only recommended way is to use properties which can be overriden.

I think this is the right approach. Just do not use public instance variables and use analogies to properties.

Regarding why is it so in Java, I think some kind of C++ like style which was adopted at that time of point when Java was designed as a way to ease transition.

Alpha01
  • 838
  • 6
  • 13
  • C# is just like Java. public fields are also considered a ad practive in Java. C# just has syntactic sugar to access properties using a field access syntax, and Java uses getters and setters, but they're the same thing. – JB Nizet Dec 28 '11 at 12:06
  • Sure thing. To be frank, i expect a better syntax for getters and setters in Java in the next version. – Alpha01 Dec 28 '11 at 12:09
  • @Jiri Pik Current syntax is fine. If you don't like'em make the fields public. I think C# syntax for properties is horrendous. – Mister Smith Dec 28 '11 at 12:42
1

There's little to override in an instance field. You'd only have to replace it with the same thing: same name, same type. You might replace an array with one of different length, but you'd need to take a close look at all the super classes to make sure they're not making assumptions about the length.

Non-private fields are, as noted by others, usually something to be avoided. Sometimes a class is more of a C structure, with public fields and no methods. This is perfectly good practice, but there's still no point in overriding anything.

Overriding is actually only about methods, without regard to language. Java does not have properties like C#, which are (limited) classes in their own right with methods to be changed. Fields can look and act like properties, but they are not the same thing at all.

RalphChapin
  • 3,108
  • 16
  • 18