I want to write a program in java that consists of three classes, A, B, and C, such that B extends A and C extends B. Each class defines an instance variable (named "x").
how can I write a method in C to access and set A's version of x to a given value, without changing B or C's version?
I tried super.x but It wasn't true.
any help?
thanks for your attention in advance
You can access A's version of x like this:
((A)this).x
as long as x wasn't declared private in class A. I've just tested it.
Note that for fields, there is no overriding (as there is for methods). Thus, for an object of class C, there will be three x fields, but two of them can't be accessed normally because they are hidden by the other field named x. But casting the object as above will allow you to get at it, if it would have been visible if not hidden.
I think it is very poor practice to declare fields of the same name in a class and its subclasses. It's confusing. It can happen legitimately if, say, you have a class A and you later change the implementation of A and add a new private field z; in that case, it may not be possible to make sure no subclasses of A already have a field z, since you don't even always know what all the subclasses are (if A is a class you've distributed publicly, for instance). I think it's for that reason that Java allows you to have fields of the same name, and why the hiding rules are the way they are, because it allows things like this to work without breaking all the other subclasses. Other than that, though, I recommend not having fields of the same name in superclasses and subclasses. Perhaps if they're all private it might be OK, though.
Do the following
public static void main(String[] args) throws Exception {
C c = new C();
System.out.println("c:" + c.x);
System.out.println("a:" + ((A)c).x);
c.changeAX();
System.out.println("c:" + c.x);
System.out.println("a:" + ((A)c).x);
}
static class A {
int x;
}
static class B extends A {
int x;
}
static class C extends B {
int x;
public void changeAX() {
((A)this).x = 4;
}
}
Fields are resolved relative to the declared type of the reference. The above prints
c:0
a:0
c:0
a:4
The field will have to have at least protected visibility.
You don't want to be hiding class members, it's bad practice because it can easily confuse anyone trying to figure out which member you are referring to.
I misread your question. You can't do what you're trying to do.
Extending classes means adding information in several layers, ultimately resulting in one object. Although there are multiple layers, this doesn't mean that the layers are separate of eachother.
The variable X will be defined at one level (probably A) and after that the other classes will use this variable (if it's declared protected), but they won't have their own copy of it. You can only access your direct superclass.
This class might give you additional access to its own superclass, but you don't have direct contact with the super-super class.
Related
This question already has an answer here:
What happens in the heap when class A inherits class B in Java
(1 answer)
Closed 3 years ago.
Consider a Superclass A and a derived class B whereas A contains a private variable x. B contains an explicit super() call as first argument inside its constructor while there might be some other variables of B like y and z. As far as I know there is no inheritance for private fields. Does that mean private fields will not get instantiated while executing:
B b = new b();
My question is: How does the heap look like after running the above code? Of course there will be y and z, but what about x in this case?
Field inheritance and field visibility are two separate concepts, not to be confused.
Field inheritance
In a way (to simplify a bit), a class is a template from making objects. So if a class A declares two fields f1 and f2, then instantiating A creates objects (and allocates memory for them on the heap) that have these two fields.
A subclass is also a template for making objects, but this template is expressed as an addition to another class. So if class B declares field f3 and extends A, it's basically saying, "take all the fields that A defines, and add f3". So instantiating B results in an object with three fields f1, f2, f3.
Field Visibility
Field visibility, as expressed through access modifiers like private and public, is a way to control which part of the code "sees" (or can refer to) a certain field. The private modifier means that no code outside of the class that declares the field can refer to this field. However, it doesn't mean that the field stops existing. To make a dodgy parallel, if you and another person are in a room and you turn off the light, you can't see the other person, but they are still there.
To emphasize the point that the concepts are separate, consider that in some cases you can see fields that are not inherited (e.g., because they are non-private, but in a class not in the same class hierarchy). And in some cases you can't see fields that are inherited, as in the case of private fields in the superclass.
The private field defined in the super class is instantiated when a statement does that.
The fact that you manipulate a subclass doesn't change anything on this point. The field is always existing and instantiable, just the subclass cannot access it directly.
If the field of the super class was not instantiable, the Java inheritance would make not any sense since the subclasses would be not consistent or even unusable as superclass methods will not work any longer.
For example :
private int x;
A(){
this.x = getIntValue();
}
int getX(){return x;}
And B the subclass :
B(int x){
super(); // in the compiled code even if not in the source code
}
new B().getX() will of course return the value of x instantiated in the superclass.
I was going through Java inheritance and I tried the following code
class A {
public int x = 1;
public void print1() {
System.out.println("Print from A");
}
}
class B extends A {
public int x = 2;
public void print1() {
System.out.println("Print from B");
}
}
class C extends B {
public int x = 3;
public void print1() {
System.out.println("Print from C");
}
public static void main(String aa[]) {
C c = new C();
((A) c).print1();
System.out.println(c.x);
System.out.println(((A) c).x);
}
}
The output was
Print from C
3
1
Now, my question is that I am able to access class A member x from class C instance c but why am I not able to access the class A method print1(). I know, if I want I can call new A().print1();. But, I want to access it from an instance of class C directly. So by overriding methods, are the top parent class methods lost in the bottom child class? However, the parent class members are retained (although hidden). Why so? And is there a way to call a method from class A in class C without creating an instance of A?
EDIT
What's happening here?
When you say ((A)c).print1();, JVM knows that actual the instance, on which it needs to call is print1() is of type C hence class C's print1() version is executed.
But when you type ((A)c).x, you are referring to state, not behavior and that too using reference of type A. Which version of x will be picked up, is decided at compile time as compiler knows what is the type reference (In this case A). That is why you see A's state.
This statement from Java doc might also be interesting for you:
Within a class, a field that has the same name as a field in the
superclass hides the superclass's field, even if their types are
different. Within the subclass, the field in the superclass cannot be
referenced by its simple name. Instead, the field must be accessed
through super, which is covered in the next section. Generally
speaking, we don't recommend hiding fields as it makes code difficult
to read.
Why is it this way?
Answer to your questions:
Question 1:
my question is that I am able to access class A member x from class C
instance c
About variable x, since it is declared as public, no business validation can be applied on that. Moreover, the developer who's declaring it as public, is aware that concept of encapsulation can't be applied now (which is obviously not recommended). So there is no harm in allowing access to parent's state using child instance. Therefore, by using ((A)c).x, you can access x from class A.
Question 2:
However, the parent class members are retained (although hidden). Why
so?
It's because Java does not allow you to use super.super.super.. arbitrarily to access any parent's behavior in the inheritance hierarchy. And the reasoning behind it is to preserve encapsulation. You can only access behavior of the immediate parent class using super keyword but not beyond that.
To explain it more, let's say you have implementation of class B like:
class B extends A {
public int x = 2;
public void print1() {
if(x >= 2) {
System.out.println("Print from B");
}
}
}
Now if super.super was allowed, you can easily bypass validation in print1() method of class B and can invoke A's print1() method from the instance of class C.
Question 3:
However, the parent class members are retained (although hidden). Why
so?
As, mentioned earlier, to retain encapsulation.
Question 4:
And is there a way to call a method from class A in class C without
creating an instance of A?
So there is no way to access print1() from A using C's instance.
When you override a function which already implemented in base(parent) class, when you call that function within the child class, automatically the class in the child will call so in your case when you call print1() of a C object:
C c = new C();
c.print1();
you will call the override function. However if in any part of your program you feel that you need to call the top parent class for any case (which cannot be fulfilled by super) then you should reconsider your design strategy; maybe you shouldn't override the print1() or even you shouldn't put print1() in the base class in the first place
In object oriented programming, only methods have the ability to be overriden. You cannot override a data member. This explains why you get the outputs.
print1() method of A is overriden in C, and c is an object of C. So, it will call the print1() method of C. On the other hand, the variable x is not overriden.
To call the superclass method, you can do:
super.print1();
Here , Same named Instance Variable is used in all the Classes to confuse the compiler, but you should know that Only Member functions can be overridden not member variables.
So, All the three x will be stored separately in memory. but public void print1() will be overridden by its child class. So,
((A)c).print1(); this piece of Code will Call the overridden method defined in class C. doesn't matter in which class you cast the Object of Class C.
But in Second Case ((A)c).x will print the value from Class A.
((A)c).x :- this will reference to the variable x belongs to Class A not to Class C. because variables never overridden in Inheritence.
((A)c).print1(); Actually it is similar to the c.print1(); .
It doesn't matter that you typecast it with Class A, it will still call print1() function of the Class C.
The question about access to protected member in Java was already asked and answered a lot of times, for example:
Java: protected access across packages
But I can't understand why it is implemented this way, see explanation from "Java Programming Language" (4 ed.):
"The reasoning behind the restriction is this: Each subclass inherits the contract of the superclass and expands that contract in some way. Suppose that one subclass, as part of its expanded contract, places constraints on the values of protected members of the superclass. If a different subclass could access the protected members of objects of the first subclass then it could manipulate them in a way that would break the first subclass's contract and this should not be permissible."
OK, that's clear, but consider this inheritance structure (extract from some code):
package package1;
public class A {
protected int x;
}
package package2;
public class B extends A {
public static void main(String[] args)
C subclass = new C();
subclass.x = 7; // here any constraints can be broken - ??
}
}
class C extends B {
// class which places constraints on the value of protected member x
...
}
Here subclass.x = 7 is a valid statement which still can break a C's contract.
What am I missing?
Edited (added): Maybe I should not apply the cited logic in this situation? If we were dealing with only one package, the no restrictions exist at all. So maybe direct inheritance chain is treated in simplified way, meaning that superclass must know what it is doing...
It's ultimately all about following contracts, as stated in your posted quote. If you're really worried that someone won't read the contract, then there's a defensive programming solution to all this that introduces validation on modification.
By this I mean that the code you posted can break contract; this, however, couldn't:
public class A {
private int x;
protected final void setX(int x) throws IllegalArgumentException {
if (x < 0)
throw new IllegalArgumentException("x cannot be negative");
subValidateX(x);
this.x = x;
}
/**
* Subclasses that wish to provide extra validation should override this method
*/
protected void subValidateX(int x) {
// Intentional no-op
}
}
Here, I've done three major things:
I made x private so it can only be assigned from within A (excluding things like reflection, of course),
I made the setter final which prevents subclasses from overriding it and removing my validation, and
I made a protected method that can be overridden by subclasses to provide extra validation in addition to mine to make sure that subclasses can narrow requirements on x, but not widen them to include things like negative integers since my validation already checked that.
There are lots of good resources for how to design for inheritance in Java, especially when it comes to super-defensive protect-the-contract API programming like my example above. I'd recommend looking them up on your favorite search engine.
Ultimately, though, the developer writing the subclass needs to be responsible enough to read documentation, especially when you get into interface implementation.
Inherited classes are implicitly friends with their parent. So as soon as C is inherited from B, it is actually normal that B has the vision on C's x attribute.
Since C extends B, having
C c = new C();
c.x = 1;
is, with respect to your issue, exactly the same as
B b = new C();
b.x = 1;
Java compiler doesn't consider the runtime type of the object referred to by b and c in the above code; all it sees is the declared type, which is B and C, respectively. Now, since my second example obviously must work (the code in class B is accessing its own property, after all), it follows that the first example must work as well; otherwise it would mean that Java allows you to do less on a more specific type, which is a paradox.
I can't seem to understand the static key word (java) so I googled it up and viewed a thread in this website, though I'm sure the answer was conclusive and clear -it always is over here- I didn't seem to understand it for two reasons; I'm not a native English speaker and the language was a bit vague for me, and it lacked exemples of use in classes, instance of classes, interfaces (if possible), instance of interfaces and variables, lists and arrays ect.
I would really appreciate any help and please keep the English as simple as possible ;)
Thank you
Aditsan
Note from editor: Please note that the original poster is asking for examples, and is not a native English speaker as you provide answers. From the comments, it appears that OP doesn't understand the concept well enough to ask about the parts that don't make sense yet, so examples would be awesome! It may take extra details and multiple different explanations to find the combination of answers that works best.
I think it helps to understand what non-static means, i.e. field/methods/... that are declared without the keyword static.
Every field declared without the keyword static exists as part of an object. If you have two objects, each of these two objects has a field with possibly different contents:
class X {
int f;
}
X x1 = new X();
X x2 = new X();
x1.f = 5;
x2.f = 10;
// x1.f still is 5
However, static fields exist not per object, but per class. So in the following example, there is only one field g no matter how many (if any!) objects of class Y you have:
class Y {
static int g;
}
Y y1 = new Y();
Y y2 = new Y();
y1.g = 5;
y2.g = 10;
// y1.g is 10, because y1.g and y2.g mean the exact same thing
I personally think accesses to static fields should be made using the class (Y.g) instead of mentioning object instances (y1.g), so that the existence without any object instance is more explicit.
For methods the difference is that non-static methods are associated to an object instance, which can be accesses using this inside the method. When invoking a method declared with void m() you can access non-static (and static) fields of the object it is invoked on (so for x1.m() from the example above you can get to the field containing 5, for x2.m() you can access the field containing 10.
Static methods, however, can be invoked without having a (corresponding?) object around. If the declaration is static void n() inside class Y, you can call this method using Y.n() or y1.n() (if y1 is an instanceof Y, as above). Here, too, I prefer the first way of writing it down. Because in static methods you do not have a reference to the object instance (which is named this in non-static methods), you cannot access specific non-static fields from inside a static method - simply because there is no clear association to a specific object.
Regarding static and class definitions: This is rather advanced. You can declare a class inside another class. If the inner class is not static, every object instance of the inner class also has a reference to an instance of the outer class (which also means that you only can create an instance of the inner class if you have an instance of the outer class). This is not always what you want. By declaring the inner class static it just exists and can be used, more or less, like a class defined in its own file.
Basically, static implies/provides two things:
1) Only one instance of an "item" exists in the whole system (JVM)
2) Static "items" are also context/state free
To explain (1) above: Suppose you have a Meal Token issuer. No matter how many users/processes are there in the system, all tokens must be issued by a single "thing". You would develop that "thing" as static. You would then decide what that "thing" is. It could be a class that does a complex operation and implements a complex business rule. Then you would have a single static class issuing tokens in "a single uniform way" for the whole system. Some times, all that matters is that the token should be "static" but how it is issued could be non-static. Then you would simply implement a "Static" token counter.
To explain (2) : Going by what is said for (1) above, you can easily see why it is important that the static "things" operate in a context-free manner. That is, they do not know who calls them or for what purpose. When they are called, they do not borrow anything from the past, they need all inputs from the current caller, and they just do their job, and remember nothing for the future.
Ok, this might be basic, but I want good programmers' opinions on this.
What is a good way to handle variables in a small class file?
I like modularizing methods and keeping methods that do really specific things.
I end up passing variables between those methods. Is it a good practice to make variables used across many methods as member variables? Or is it better to pass the variables to methods?
For example:
class Test{
somefunction(int a, int b, int c, int d) {
doSomething(a, b, c);
doOneMoreThing(a, c, d);
}
void doSomething(int a, int b, int c) { }
void doOneMoreThing(int a, int c, int d) { }
}
In the above example, do you think the variables should be kept as member variables?
Please explain why one methodology is preferred over the other.
Do you need to keep the variables around between method calls, and reuse their value? If so, they should be class members. (At least in some class - not necessarily this one.)
Otherwise it is somewhat a matter of taste. One important factor is though that local variables don't add state to the object, which can be useful if it is used concurrently. Keeping all variables local may even allow you to make your class immutable, which usually makes it automatically thread-safe. But even in a single-threaded environment an immutable class is easier to understand and maintain.
OTOH passing lots of parameters around can be awkward. You may consider introducing a Parameter Object to alleviate this problem.
If I have some variables that I would end up passing to a bunch of private methods, I'll often move them into a private inner worker class.
Instead of
class Foo {
public doSomething(...) {
// some setup
doSomethingRecursively(a, b, c);
}
private void doSomethingRecursively(A a, B b, C c) {
if (baseCase) { ... }
doSomethingRecursively(a + 1, b, c);
}
}
I'll move the variables that never difference into properties on a worker.
class Foo {
public doSomething(...) {
// some setup
new AppropriatelyNamedHelper(b, c).doSomethingRecursively(a);
}
private static final class AppropriatelyNamedHelper {
final B b;
final C c;
AppropriatelyNamedHelper(B b, C c) {
this.b = b;
this.c = c;
}
void doSomethingRecursively(A a) {
if (baseCase) { ... }
doSomethingRecursively(a + 1);
}
}
}
This makes it clear to a reviewer what in each scope is invariant within that scope.
Member variables should exist to maintain some kind of state in a class. If your class maintains state then definitely define member variables for those things you need to track. If a class does not maintain state then there is no reason to make things members (I have had to debug legacy code where variables should not have been made members but were and it was causing errors when making multiple calls to the object because the state was unpredictable).
However, while you might like "modularizing" functionality, read up on coupling vs. cohesion. There is a balance to be struck between having too much functionality in a class but fewer dependencies and having very little but highly specific functionality and lots of dependencies.
Having useless member variables is usually regarded to as bad design.
But you can (and should) combine multiple variable sets into a new class if you use that variables in lots of methods.
If you don't care about the state of the object, then passing the variables to the method is fine. In that case, I would use a static modifier on the method, then you don't have to instansiate the class and you can call the method like so:
Test.doSomething(1, 2, 3);
Instance Variables: Their values are unique to each instance of a class. When an object is allocated in the heap, there is a slot in it for each instance variable value. Therefore an instance variable is created when an object is created and destroyed when the object is destroyed.
Class Variable: The Class variables are declared with a static keyword/modifier.There is only one copy of class variable no matter how many times the class is instantiated. They are stored in static memory.
Local variables: Only accessible within the method they are declared. When a method is entered, an area is pushed onto the call stack. This area contains slots for each local variable and parameter. When the method is called, the parameter slots are initialized to the parameter values. When the method exits, this area is popped off the stack and the memory becomes available for the next called method.
If you are going to reuse the variables, then you can declare them as class variables. If not, then they should be local variables defined in their respective methods.
First of all Somefunction(... } is a syntax error. Second, method names should start with lower case letters, and class names should start with upper case. Third, we have no idea what the best way is without knowing what these methods do, what they're used for, and where their parameters come from
Depends on how often you have to change your code (or you should think about how often you're going to change it when you design it). If the signature changes you have to change it in a lot of places. That means more code to test even when you refactor the signature. I would err on the side of creating member variables and encapsulating.