5

It's been quite awhile since I worked on anything in Java, and I really have very limited experience making anything with it at all, for the most part I write in higher level specified languages, scripting languages and the sort.

I assume I'm not understanding the concept behind assigning the default value of a class's members.

// parent
public class A {
    protected int value = 0;
    public void print() {
        System.out.println(value);
    }
}

// child class
public class B extends A {
    int value = 1;
}

To keep it short, creating an instance of B and calling print() prints the original value of "value" set in A.

I assume rather than being some kind of general identifier for "a variable named 'value' owned by this object," the defined function on A has a completely different context for "value" than B does.

What other method is there to organize common variations of a certain class but creating a child of said class? Some kind of factory object? It doesn't seem to be interfaces are the answer because then I have to redefine every single facet of the class, so I've gained nothing in doing so.

Any help would be much appreciated, thanks.

milkmanjack
  • 77
  • 1
  • 4
  • 2
    Declaring `value` in `B` is hiding the `value` in `A`. You need to make a constructor for `B` and set `value=1` there. – azurefrog Dec 17 '14 at 18:42
  • 3
    See [hiding fields](http://docs.oracle.com/javase/tutorial/java/IandI/hidevariables.html) for more information. – azurefrog Dec 17 '14 at 18:48
  • Field hiding isn't the culprit in this question. With field hiding, B.value would hide A.value. Instead, the OP is getting A.value, and expecting B.value. – Andy Thomas Dec 17 '14 at 19:14
  • I wonder if `A.this.value` and `B.this.value` would work. – sybear Dec 17 '14 at 19:27

2 Answers2

6

Subclass fields do not override superclass fields.

You can set a default value through constructors, as illustrated below.

// parent
public class A {
    private int value = 0;
    public A( int initialValue ) {
        value = initialValue;
    }

    public void print() {
        System.out.println(value);
    }
}

// child class
public class B extends A {
    public B() {
       super( 1 );
    }
}

Also, in most cases, your life will be easier if you avoid protected fields.

Protected fields open your data to direct access and modification by other classes, some of which you may not control. The poor encapsulation can allow bugs and inhibit modification. As suggested in the Java tutorials on access control:

"Use the most restrictive access level that makes sense for a particular member. Use private unless you have a good reason not to."

Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
  • "In most cases, your life will be easier if you avoid protected fields." This may be true, but probably deserves more explanation. – dnault Dec 17 '14 at 18:55
  • @dnault - Added explanation. Thanks for the idea. – Andy Thomas Dec 17 '14 at 19:05
  • This is pretty much the conclusion I came to after a few minutes of fiddling with it. I kind of dislike the idea of having to set the values during creation of the object since I'm so used to redefining members in subclasses just overriding the values, but this seems to be what the object oriented paradigm calls for (I think C++ doesn't let you override either?). Thanks for the input. – milkmanjack Dec 18 '14 at 03:58
  • In both Java and C++, alternatives include: 1) defining a protected or public setter method in the superclass, and 2) defining and consistently using a getter method [in C++, declared `virtual`], which can be overridden by a subclass. – Andy Thomas Dec 18 '14 at 04:35
4

@user2038045 - good question.

The source of your confusion is that in Java, a subclass can override methods ... but cannot override member variables.

If your class B had it's own "print()" method - you'd see the behavior you expected. B.print() would override A.print().

If your class B had any other method that accessed "value", you'd again see the behavior you expected. B.value would hide A.value, and B.someOtherMethod() would access B.value.

But in your case, you called A.print() ... which accesses A.value.

Here are more details:

Is there a way to override class variables in Java?

Community
  • 1
  • 1
FoggyDay
  • 11,962
  • 4
  • 34
  • 48