I have these two classes in different packages(named a and b)
package a;
import b.*;
public class Tree
{
int health = 100;
public void show()
{
System.out.println(this.health);
}
public static void main(String[] args)
{
Arb c = new Arb();
//System.out.println(c.health); is not visible
c.show();
}
}
package b;
import a.*;
public class Arb extends Tree
{
}
I know that field health can't be accesed by an instance of type Arb because is not visible,so it doesn't exist for an instance of Arb. All that it inherited is the public void show() method. Ok until now.
But from my tests, calling method show through object c outputs the answer 100,as the initial value for a Tree object.
My problem with understanding this is: The method calls this.health ,so as long as object c calls this method, this = c. But health shouldn't be visible...
Could someone explain what is actually happening there? Thank you!
Your statement "so it doesn't exist" is incorrect. It exists, it's just not visible.
An instance of Arb is also an instance of Tree, and code in Tree can see the field, while code in Arb cannot see it.
As you correctly said, the Arb class inherits the public show() method of the Tree class. When calling the method show() of the class Arb you are actually calling the show() method in Tree. Because this method can see the field health it can also print it's value.
Related
Having trouble understanding the intricaies of upcasting/downcasting, and static binding and dynamic bidning in these cases. Please consider the following classes and interface example:
public class Marsupial { private String name;
Marsupial(String name) {
this.name = name;
}
void eats() {
System.out.println("Eats #1");
}
String getName(){ return name;
}
}
abstract class Herbivore extends Marsupial {
Herbivore(String name) {
super(name);
}
void eats() {
System.out.println("Eats #2");
}
abstract void chews(boolean b);
}
interface Australian {
public void greets(Koala k);
}
public class Koala extends Herbivore implements Australian {
Koala(String name) {
super(name);
}
public void greets(Koala k) {
System.out.println("G'day mate!");
System.out.println(getName() + " " + k.getName() );
}
void chews(boolean b) {
System.out.println("Yum yum!");
}
void chews(int i) { System.out.println("Delicious!");
}
void likes(Koala k) {
greets(k);
k.greets(this); }
}
Now when I make a driver class to use all of the classes I notice some odd things happening that I am not sure why.
For example,
public class Driver {
public static void main(String[] args) {
Marsupial m = new Marsupial("Kate");
Marsupial m2 = new Koala("Kim");
System.out.println(m.getClass() == m2.getClass());
}
}
This turns out to be false. They are not the same class. So what is happening here exactly. We have Marsupial on the left and something else on the right. So does what's on the right the only thing that matters when we are calling methods? When the compiler runs and looks at methods does is check the right side of the equals operator and say ok this is such and such class, therefore use the methods of the class defined on the right side when figuring out whose class to use.
Also,
if inside the main method I wrote:
Marsupial m = new Koala("jack");
m.eats();
This prints out Eats #2. Now is this because since Koala does not have a eats method is just goes back one level up the chain, so the next level up would be Herbivore and since that has an eats() method that is what gets called, is that the idea there?
Another example in the main method:
Herbivore h = new Koala("June");
((Marsupial)h).eats();
Here the thing that throws me off is that we can use abstract classes as a reference to actual objects, like here Herbivore is an abstract class therefore cannot be instaniated, but it can be assigned to a class that does instantiate an object.
But what confuses me most is that now we are in the Koala class and we call the eats() method but then we UPCAST the variable to Marsupial. So does that automatically put us in the Marsupial class and therefore anytime we call a method even if its in other classes the Marsupial class method is the one that gets called since we typecasted it to Marsupial, therefore its Eats #1.
Another area of confusion is if we do this in main:
Australian a = new Koala("Khloe");
a.chews(true);
It's werid seeing an interface be assigned to a subclass instantiation. It confuses me what would get called with a.chews(true). So since it's been defined as a Koala object then we are IN the Koala class and must use Koala methods if they exist, and if not there we go one level up to check that they have that method and so on and so fourth. But here the method is invalid. So does it only work if Australian had a prototype method in there and Koala defined it? then it would work? Is that the idea behind setting interfaces as objects of their subclasses? Even though Koala has that method since Australian does not, it will not work.
And if we have the code in main like:
Herbivore h = new Koala("Stacy");
h.chews(true);
this will print out "Yum yum" only because Herbivore had that prototyped undefined method and Koala defined it. But if Herbivore didn't have that prototype method is wouldn't work.
The last question I have is if this were run in main:
Herbivore h = new Koala("Kali");
h.chews(4);
This won't work because despite the fact that Koala has this method in there, it's not defined in Herbivore, so it's invalid.
Please help, any corretions or information you could provide would be very helpful.
Thank you
The answer to all is one: as far as
the JVM is concerned it doesn't
care one bit about the variable
type, but only the actual type (the
one used with the new keyword)
. Variable types are for the
compiler only to ensure type
safety as early in development
possible.
I have two classes Test and Encap. I have a private variable a and access via setter and getter method. and i'm inheriting the class Test with Encap.
now i am able to change the value of a using setValue(int a). i want to restrict that option. i want it to make it as a read only value. please assist me in this.
class Test
{
private int a;
protected void setValue(int a)
{
this.a = a;
}
protected void getValue()
{
System.out.println("The assigned value of a is : "+this.a);
}
}
public class Encap extends Test {
public static void main(String [] args)
{
Test t = new Test();
t.setValue(4);
t.getValue();
Encap e = new Encap();
e.setValue(3);
e.getValue();
}
}
One option would be to delete the method setValue() from the class Test:
class Test
{
private int a;
protected void getValue()
{
System.out.println("The assigned value of a is : "+this.a);
}
}
Edit:
Why to do this? If Encap inherits from Test, it should be able to do the same actions as Test. Otherwise, what's the purpose of inheriting? If you still thinking that Test should be able to modify the value and Encap not, maybe your design is wrong. You could try something like this instead:
BaseClass
---------
+getValue
/ \
/ \
Test Encap
-------- ---------
+setValue
If you mean that you want a derived class to not expose public methods of the superclass, then your code probably 'smells'...
Remember that Inheritance models "Is A"
So in your example an Encap is a Test and you should be able to do anything to an Encap that you can do to a Test.
However, if you simply must inherit from a class where you don't want to expose a parent-class method, you can override the method and have its body do nothing. But for simple getter and setter accessor methods this is potentially very confusing for clients of your code.
If you can't reconcile things and calling setValue() on an Encap is never the right thing to do, i would recommend overriding the method, commenting it liberally and have it do nothing, or throw an exception to indicate to the client that they're doing something that doesn't make sense.
I was working on SCJP6 dumps when I found this confusing exercise:
Given classes defined in two different files:
package packageA;
public class Message {
String getText() { return “text”; }
}
And:
package packageB;
public class XMLMessage extends packageA.Message {
String getText() { return “<msg>text</msg>”;}
public static void main(String[] args) {
System.out.println(new XMLMessage().getText());
}
}
What is the result of executing XMLMessage.main?
A. text
B. Compilation fails.
C. <msg>text</msg>
D. An exception is thrown at runtime.
The answer was: B, but I don't understand why; I think the answer should be C.
If the code you posted it's the one that is in the book, the correct answer as you mentioned is C, let me explain why.
Again, assuming you copied the code as it's shown in the book when you do, the following line:
String getText() { return “<msg>text</msg>”;}
Its not overriding the getText() method in packageA.Message class but declaring a new one, that will can be accessed for XMLMessage instances within packageB.
This would be different if the the main method is something like:
public static void main(String[] args) {
Message message = new XmlMessage();
System.out.println(message.getText());
}
In this case there is a compilation error since the Message.getText() methods is not exposed outside the package.
A package default method cannot be overridden because it is not visible in another package.
In your example, method getText() in class Message is only visible to members of packageA.
Method does not override package visible method in Eclipse
The method String getText() { return “text”; } is with package (default) scope . And hence it is not visible outside the package packageA .
so it is not possible to override the method in the class XMLMessage which is outside the packageA .
You can learn the basics of method overloading and overriding here
I just had some method calling scenarios I was unsure of, and was hoping someone could help clear some up for me.
a) If I was in the SalesMethod class and I wanted to call the sales method from the region method how would I do that? (private method calling public method)
b) What about sales calling purchase? (public calling public from within same class)
c)If I was in SalesMethod, what would be a way to call the futureSales method? Would I have to create an instance for it since it's non static?
Thanks in advance.
public class SalesMethod
{
public static double sales ()
{
code
}
private static void region ()
{
code
}
public static double purchase ()
{
code
}
public void futureSales ()
{
code
}
}
a) private method calling public method is ok since public mean "visible from everywhere".
public static double region()
{
sales();
}
b) public method calling public method is ok for the same reason.
b') public method calling private method is ok if the private method is in the same class than the public one.
c) to call a non-static method, you have to create an instance since you call it "on" an object. You can't call it from a static method the way you do in the example above.
static means "relative to a class"
non-static is relative to an object, you can see that as an action performed by the object.
If I was in the SalesMethod class and I wanted to call the sales method from the region method how would I do that? (private method calling public method)
They are both static, so you can call them everytime you need to.
sales();
// Or
SalesMethod.sales();
What about sales calling purchase? (public calling public from within same class)
They are both static, so you can call them everytime you need to.
purchase();
// Or
SalesMethod.purchase();
If I was in SalesMethod, what would be a way to call the futureSales method? Would I have to create an instance for it since it's non static?
Yes.
SalesMethod instance = new SalesMethod();
instance.futureSales();
Lets suppose I have the following two classes
public class alpha {
public alpha(){
//some logic
}
public void alphaMethod1(){
//some logic
}
}
public class beta extends alpha {
public beta(){
//some logic
}
public void alphaMethod1(){
//some logic
}
}
public class Test extends beta
{
public static void main(String[] args)
{
beta obj = new beta();
obj.alphaMethod1();// Here I want to call the method from class alpha.
}
}
If I initiate a new object of type beta, how can I execute the alphamethod1 logic found in class alpha rather than beta? Can I just use super().alphaMethod1() <- I wonder if this is possible.
Autotype in Eclipse IDE is giving me the option to select alphamethod1 either from class alpha or class beta.
You can do:
super.alphaMethod1();
Note, that super is a reference to the parent class, but super() is its constructor.
Simply use super.alphaMethod1();
See super keyword in java
You can't call alpha's alphaMethod1() by using beta's object But you have two solutions:
solution 1: call alpha's alphaMethod1() from beta's alphaMethod1()
class Beta extends Alpha
{
public void alphaMethod1()
{
super.alphaMethod1();
}
}
or from any other method of Beta like:
class Beta extends Alpha
{
public void foo()
{
super.alphaMethod1();
}
}
class Test extends Beta
{
public static void main(String[] args)
{
Beta beta = new Beta();
beta.foo();
}
}
solution 2: create alpha's object and call alpha's alphaMethod1()
class Test extends Beta
{
public static void main(String[] args)
{
Alpha alpha = new Alpha();
alpha.alphaMethod1();
}
}
It is possible to use super to call the method from mother class, but this would mean you probably have a design problem.
Maybe B.alphaMethod1() shouldn't override A's method and be called B.betaMethod1().
If it depends on the situation, you can put some code logic like :
public void alphaMethod1(){
if (something) {
super.alphaMethod1();
return;
}
// Rest of the code for other situations
}
Like this it will only call A's method when needed and will remain invisible for the class user.
Whenever you create child class object then that object has all the features of parent class.
Here Super() is the facilty for accession parent.
If you write super() at that time parents's default constructor is called.
same if you write super.
this keyword refers the current object same as super key word facilty for accessing parents.
Solution is at the end of this answer, but before you read it you should also read what is before it.
What you are trying to do would break security by allowing skipping possible validation mechanisms added in overridden methods.
For now lets imagine we can invoke version of method from superclass via syntax like
referenceVariable.super.methodName(arguments)
If we have classes like
class ItemBox{ //can sore all kind of Items
public void put(Item item){
//(1) code responsible for organizing items in box
}
//.. rest of code, like container for Items, etc.
}
class RedItemsBox extends ItemBox {//to store only RED items
#Override
public void put(Item item){ //store only RED items
if (item.getColor()==Color.RED){
//(2) code responsible for organizing items in box
}
}
}
As you see RedItemsBox should only store RED items.
Regardless which of the below we use
ItemBox box = new RedItemsBox();
RedItemsBox box = new RedItemsBox();
calling
box.put(new BlueItem());
will invoke put method from RedItemsBox (because of polymorphism). So it will correctly prevent BlueItem object from being placed in RedItemBox.
But what would happen if we could use syntax like box.super.put(new BlueItem())?
Here (assuming it would be legal) we would execute version of put method from ItemBox class.
BUT that version doesn't have step responsible for validating Item color. This means that we could put any Item into a RedItemBox.
Existence of such syntax would mean that validation steps added in subclasses could be ignored at any time, making them pointless.
There IS a case where executing code of "original" method would make sense.
And that palce is inside overriding method.
Notice that comments //(1) .. and //(2).. from put method of ItemBox and RedItemBox are quite similar. Actually they represent same action...
So it makes sense to reuse code from "original" method inside overriding method.
And that is possible via super.methodName(arguments) call (like from inside put of RedItemBox):
#Override
public void put(Item item){ //store only RED items
if (item.getColor()==Color.RED){
super.put(item); // <<<--- invoking code of `put` method
// from ItemBox (supertype)
}
}
beta obj = new beta();
Since you have created beta object , you cant refer directly to alphamethod1 of alpha object.
It can be modified as
class Beta extends Alpha
{
public void alphaMethod1()
{
super.alphaMethod1();
}
}