I'm not sure how exactly to phrase my question.
So, I have an interface reference and I'm creating a new object. The new object obviously implements said interface. The initial class inherits another class. That sub-class inherits the super class. However, I cannot access data from super class from the main method without casting the reference first. I'll show an example below
public class a {
public int getSomeData1() {
return someData;
}
}
public class b extends a implements someInterface {
// Some behavior.
}
public class c extends b implements someInterface {
// Some behavior.
}
public class Main {
public static void main(String[] args) {
someInterface obj = new b();
obj.someData1(); // I cannot access someData1().
c anotherObj = new c();
c.getSomeData1(); // This works however.
}
}
How can I have obj.someData1() actually get the data from class a rather than casting it to a.
Just remember the rule that method invocations allowed by the compiler are based solely on the declared type of the reference, regardless of the object type.
If it is not very clear, here is another version of this rule: what is on the left side defines methods you can call, no matter what is on the right :)
Here are a few examples to make it more clear:
public interface Animal {
void voice();
}
public class Dog implements Animal {
public void voice() {
System.out.println("bark bark");
}
public void run() {
// impl
}
}
When you create a dog like this:
Animal dog1 = new Dog();
The reference type which is Animal defines which methods are allowed for you to call. So basically you can only call:
dog1.voice();
When you create a dog like this:
Dog dog2 = new Dog();
The reference type which is Dog, so you are allowed to call:
dog2.voice();
dog2.run();
This rule remains also when you have class inheritance, not only when you implement an interface. Let's say we have something like:
public class SpecialDog extends Dog {
public void superPower() {}
}
And those are examples of what you can call:
Animal dog1 = new SpecialDog();
dog1.voice(); // only this
Dog dog2 = new SpecialDog();
// here you can call everything that Dog contains
dog2.voice();
dog2.run();
SpecialDog dog3 = new SpecialDog();
// here you can call all 3 methods
// this is the SpecialDog method
dog3.superPower();
// those 2 are inherited from Dog, so SpecialDog also has them
dog3.voice();
dog3.run();
In other cases, you need to upcast/downcast to be able to call some specific method.
Happy Hacking :)
Related
Suppose I have a class that extends another class and implements one or more interfaces. How can I specify a type that requires such condition?
For example:
class Eagle extends Animal implements Fly {
}
class Falcon extends Animal implements Fly {
}
public static void main (){
??? anAnimalWhoCanFly;
}
Update: I removed the list. Just suppose I want to have an object that is an object of a class that extends Animal and implements Fly.
Thanks
If you want a way to specify, say, "a type that extends Animal and implements Fly", just define a class that does exactly that:
public abstract class FlyingAnimal extends Animal implements Fly{ }
Now you have Eagle and Falcon extend from FlyingAnimal rather directly from Animal:
public class Falcon extends FlyingAnimal {
public void fly(){ System.out.println("I'm a fast flier");
}
public class Eagle extends FlyingAnimal {
public void fly(){ System.out.println("I'm built for soaring");
}
public class Cat extends Animal {
// I'm a cat; I can't fly
}
Now you can do something like this:
public void flyIt(FlyingAnimal fa){
fa.fly();
}
public void test(){
Falcon falcon = new Falcon();
Animal eagle = new Eagle();
Animal cat = new Cat();
flyIt(falcon); // OK: `Falcon` is a `Falcon`, which is also
// a `FlyingAnimal`
flyIt(cat); // COMPILE ERROR: `cat` is an `Animal`,
// which is not a subclass of `FlyingAnimal`
flyIt(eagle); // COMPILE ERROR: `eagle` is an `Animal`, which is
// not a `FlyingAnimal`
flyIt((Eagle)eagle);
// OK: because we know that `eagle` actually references
// an `Eagle`, we know the type-cast `(Eagle)eagle`
// will succeed at run-time; `Eagle` is a `FlyingAnimal`
// and thus is acceptable as an argument to `flyIt`
flytIt((FlyingAnimal)eagle);
// OK: because we know that `eagle` actually references
// an `Eagle`, which in turn is a `FlyingAnimal`, we
// know the type-cast `(FlyingAnimal)eagle` will
// succeed at run-time
flyIt((FlyingAnimal)cat);
// RUN-TIME ERROR: `cat` references a `Cat`, which is
// an `Animal` but not a `FlyingAnimal`, and so will
// not successfully convert to a `FlyingAnimal` at
// run-time.
It is sad that we cannot do it in java, if #EvgenyTanhilevich is right.
I found something that somehow does what I want. It is not exactly what I wanted, because it does not require that object MUST be an instance of class that implements Fly, but still let me call fly function:
public class Main {
public static void main(String[] args) {
Eagle eagle = new Eagle();
((Fly)eagle).fly();
}
}
I am trying to learn java. Forgive me if my concepts are not clear or very wrong.
I am trying to create inheritance and polymorphism application.
I have created an array of Animals[5]. I am trying to add refrences of dog, cat to the array.
I want it to hold
Animals[0] = zooDog
I am getting error that
cannot make a static reference to the non-static
I have create AnimalstestDrivve class
package animals;
public class AnimalstestDrive {
public Animals[] myZoo = new Animals[5];
int zooCounter = 0;
public static void main(String[] args) {
//Set animals array
Dog zooDog = new Dog();
addAnimals(zooDog);
Cat zooCat = new Cat();
addAnimals(zooCat);
}
public void addAnimals(Animals a){
if ( zooCounter > 5 ){
myZoo[zooCounter] = a;
zooCounter++;
}
else
System.out.println("Zoo is full");
}
}
here is my Animals class
package animals;
public abstract class Animals {
private String Name;
private int Size; //Size on the scale 1 to 10
public void eatFood(){
System.out.println("I am eating food");
}
public void sleep(){
System.out.println("I am sleeping now");
}
abstract public void makeNoises();
}
Simple dog, cat class
package animals;
public class Dog extends Animals {
public void makeNoises(){
System.out.println("Bow! bow!");
}
}
The main method (static) attempts to call the addAnimals method, whose declaration is non-static. You need to create an instance of the class first, then call the method on this instance
AnimalstestDrive testDrive = new AnimalstestDrive();
Dog zooDog = new Dog();
testDrive.addAnimals(zooDog);
See Understanding Class Members for more information
You need to have an instance of the class AnimalstestDrive. Static means, that you don't need any instance of the class to use the class method, so if you would mark the addAnimals as static, You could use that method without creating an instance of AnimalstestDrive.
Because the method addAnimals is not static, you need to create an instance of AnimalstestDrive to use that function.
When a method is not static, it is specific to an instance of that class. For example:
AnimalstestDrive atd = new AnimalstestDrive();
atd.addAnimals(new Dog()); // this will add animals to "atd"
If a method is static, it is not specific to an instance of the class, but the class itself.
If you put this method in the class AnimalstestDrive:
public static void staticMethod() {
}
You could only access it with AnimalstestDrive.staticMethod(), not atd.staticMethod().
More info on static methods here.
Lets say that we have:
interface A{
void foo();
}
class B implements A{
void foo(){}
void doNothing(){}
}
I create a B instance
A object=new B();
Why at object.doNothing() call is a compile error raised?
Because, in compile time, Compilter check for reference type method binding. So the method doNothing() is not available in the interface A
At compile time the compiler can't be sure if the call to the method doNothing() on these references actually refer to which version of the method - the super class version or the sub class version.
Because object is A and A has no method named doNothing. If you wanted to do the doNothing method, either add it to interface A:
interface A {
void foo();
void doNothing();
}
or create object as B not A.
B object = new B();
You are using "polymorphism". This is the technique when you use an object as its parent.
Assume this implementation:
public interface Animal {
public void go();
}
class Dog implements Animal {
public void go() {
walk();
}
}
class Fish implements Animal {
public void go() {
swim();
}
}
class Duck implements Animal {
public void go() {
fly();
}
}
Now you can do something like:
Animal[] animals = {new Dog(), new Fish(), new Duck()};
Now whenever you want an animal to go, you can simply call the go(); method of the preferred array element as an animal (without any worry about their type of movement)
By now, can you ask a fish to walk? No. Because not all animals know walking.
This is why you can't call the child's method, on parent object, because the parent sees its children same and it just knows about going not walking, etc.
In your question, A interface just knows about void foo(); method and has no idea about void doNothing(); method.
Because the type A has no #doNothing method, and the variable object has the compile time type A.
Because object is A and in class A you dont have any function named doNothing.
Your code sees object with the external interface of A and as A has no method doNothing a compile error arises.
I have class Animal and two subclasses Tiger and Eagle. Both of subclasses have hunt method which is pretty much the same. The only difference between them is type of Victims. Method hunt is using generic class Field<T> for seekeing victims. It looks like this:
Tiger
void hunt(){
Field<Cattle> field = new Field<Cattle>();
List<Cattle> list = field.getObjects();
...
Eagle
void hunt(){
Field<Rabbit> field = new Field<Rabbit>();
List<Rabbit> list = field.getObjects();
...
Is there any way to perform something like that?
void hunt(Object type){
Field<type> field = new Field<type>();
List<type> list = field.getObjects();
I know that I can get list full of Object type and use instanceof later, but here we come to second question:
Is it possible to call if( object instanceof instanceOfSomeClass)?
You can use generics to achieve what you want:
public class AnimalsGenerics<E> {
public void Hunt(E prey){
...
}
}
and implement your animals specifying the prey:
public class Tiger extends AnimalsGenerics<Buffalo> {
}
But my personal implementation would be using interfaces to specify what does the animal do, for example: what happens if the animal is not a hunter, for example an herbivorous, would you need to implement your animal class again? follow the principle of leaving the implementation to the interfaces and not the heritance would help you to have a cleaner code, my dessign would be:
To design the behaviour:
public interface CollectFoodBehaviour<E> {
void collectFood(E prey);
}
Class animal would be:
public class Animal<E> {
CollectFoodBehaviour<E> collectFoodBehaviour;
public void goToGetFood(E food){
collectFoodBehaviour.collectFood(food);
}
}
Implementing the hunting behaviour:
public class HuntAnimalsBehaviour<E> implements CollectFoodBehaviour<E> {
#Override
public void collectFood(E prey) {
//implemenet the generic hunting process
}
}
and an animal instance as an example:
public class Dog extends Animal<Rabbit> {
public Dog(){
this.collectFoodBehaviour = new HuntAnimalsBehaviour<Rabbit>();
}
}
Is it possible to call if( object instanceof instanceOfSomeClass)?
No, instanceof tests if an object is an instance of a class, not an instance of an instance (as if the left side is a non-static reference and the right side is static reference); You can, however, not declare your instance
// JButton b = new JButton();
// if (b instanceof Component) can be replced with
if (JButton.class.newInstance() instanceof Component)
// or
if (new JButton() instanceof Component)
if for some odd reason you find this useful.
If I understood correctly, you can use a generic method using following code:
If you pass the object class, not the instance, you can construct a Field instance using the Class passed as parameter.
public class MyAnimal {
public <T> void hunt(Class<T> type) {
Field<T> field = new Field<>();
List<T> list = field.getObjects();
if (type == Cattle.class) {
System.out.println("Type is a Cattle");
} else {
System.out.println("Type is not a Cattle, is a " + type.getName());
}
}
public static void main(String[] args) {
new MyAnimal().hunt(Cattle.class);
new MyAnimal().hunt(new Cattle().getClass());
}
}
About your second question, if you have the Class type, you can ask with a simple: type == MyClass.class.
Hi I'm wondering if there is a simple solution to my problem,
I have an ArrayList:
ArrayList <Animal> animalList = new ArrayList<Animal>();
/* I add some objects from subclasses of Animal */
animalList.add(new Reptile());
animalList.add(new Bird());
animalList.add(new Amphibian());
They all implement a method move() - The Bird flies when move() is called.
I know I can access common methods and properties of the super class by using this
public void feed(Integer animalIndex) {
Animal aAnimal = (Animal) this.animalList.get(animalIndex);
aAnimal.eat();
}
That's fine - but now I would like to access the move() method the subclass Bird has.
I could do this by casting the Animal as a Bird:
Bird aBird = (Bird) this.animalList.get(animalIndex);
aBird.move();
In my situation I don't want to do this, as it will mean I have 3 different sets of the above code one for each subtype of Animal.
It seems a bit redundant, is there a better way?
There really isn't a nice way to do this from the superclass, since the behavior of each subclass will be different.
To ensure that you're actually calling the appropriate move method, change Animal from a superclass to an interface. Then when you call the move method, you'll be able to ensure that you're calling the appropriate move method for the object you want.
If you're looking to preserve common fields, then you can define an abstract class AnimalBase, and require all animals to build off of that, but each implementation will need to implement the Animal interface.
Example:
public abstract class AnimalBase {
private String name;
private int age;
private boolean gender;
// getters and setters for the above are good to have here
}
public interface Animal {
public void move();
public void eat();
public void sleep();
}
// The below won't compile because the contract for the interface changed.
// You'll have to implement eat and sleep for each object.
public class Reptiles extends AnimalBase implements Animal {
public void move() {
System.out.println("Slither!");
}
}
public class Birds extends AnimalBase implements Animal {
public void move() {
System.out.println("Flap flap!");
}
}
public class Amphibians extends AnimalBase implements Animal {
public void move() {
System.out.println("Some sort of moving sound...");
}
}
// in some method, you'll be calling the below
List<Animal> animalList = new ArrayList<>();
animalList.add(new Reptiles());
animalList.add(new Amphibians());
animalList.add(new Birds());
// call your method without fear of it being generic
for(Animal a : animalList) {
a.move();
}
You dont need to do any casting. The overridden method should get called [simple polymorphism]
Animal aAnimal== this.animalList.get(animalIndex);
aAnimal.move();
Above code should call bird method if object is of bird, isn't it?
And casting is not a solution , how will you decide which object to cast? You will have to use instanceOf.
In your case,the following could work,but time complexity is O(n):
public void moveBird(){
for(Animal aminal:animalList){
if(animal instanceof Bird){
aninmal.move();
}
}
}
Bird getMyBird(Integer aniInteger) {
Bird b = new Bird();
//Do somthig with bird object...
return b;
//get your modifeid bird object
}
Bird myBird = animalList.get(animalIndex);
myBird.move();