When the below code is compiled the compiler shows an error:
InterfaceTest.java:19: error: cannot find symbol knightObj.dispBK();
public class InterfaceTest{
public static interface Knight{
public void embark();
}
public static class BraveKnight implements Knight{
private int id;
public BraveKnight(int id){
this.id = id;
}
public void dispBK(){
System.out.println("ID: "+id);
}
public void embark(){
System.out.println("ID: "+id);
}
}
public static void main(String[] args){
Knight knightObj = new BraveKnight(101);
knightObj.dispBK();
}
}
What may be the possible cause?
Knight is your interface, it does not define a method called dispBK(). Your knightObj object is of type Knight, so you need to cast it to BraveKnight to be able to call the dispBK() method.
Alternatively you could add the dispBK() method into your interface.
Your third option is to initialize your object like this: BraveKnight knightObj = new BraveKnight(101);.
I warmly recommend using some IDE such as Eclipse, they will catch easy errors like this.
As stated in the documentation:
When you define a new interface, you are defining a new reference data
type. You can use interface names anywhere you can use any other data
type name. If you define a reference variable whose type is an
interface, any object you assign to it must be an instance of a class
that implements the interface.
dispBK() is method of class.
& Knight is interface and method is not declared in interface so you can't.
add :
public void dispBK(); in your interface and then it will work.
An Interface reference can hold Object of IMPL if only that all methods declared in interface.
OR you ll have to access that method using Impl object.
Add public void dispBK() to interface and then you can implement it
Method from child is not visible to parent. Here knightObj is an instance of parent interface Knight and you are trying to invoke a method of its child which is not visible. You should either add that dispBK() method to Kinght interface or use casting like ((BraveKnight)knightObj).dispBK();
An interfaace defines the minimum set of methods that the concrete class has to implement. That way you know that if you have a range of Knight objects (such as BraveKnight, CowardlyKnight and GoodKnight) they must all define the embark() method.
If you define your KnightObj variable as the Knight interface, then the methods of Knight are the only ones that are directly accessible.
However, you have instantiated your KnightObj as a new BraveKinght(101), this means that you can still access the additional methods of BraveKnight, if you cast your variable using
(BraveKnight)KnightObj.dispBK();
More detailed EXAMPLE:
You use this when passing parameters to functions or inside arrays, collections, such as
ArrayList<Knight> allKnight = new ArrayList<Knight>();
allKnight.add(new BraveKnight(105));
allKnight.add(new CowardlyKnight(13));
allKnight.add(new GoodKnight(88));
To test which concrete class you actually have, you use instanceof to evaluate it, ie
for (Knight eachKnight : allKnight) {
// No need to cast this, as all Knightly objects must implement it.
eachKnight.embark();
if (eachKnight instanceof BraveKnight) {
(BraveKnight)eachKnight.dispBK();
} else if (eachKnight instanceof CowardlyKnight) {
(CowardlyKnight)eachKnight.runaway();
} // no test for GoodKnight - he's always good
}
Related
I have a Cube object with a public 'x' field. I have a toString method in my Cube class which prints out the x,y,z fields, but when I directly access it, I get an error where: field cannot be resolved or is not a field.
public <T> void setPosition(T object){
System.out.println(object);
System.out.println(object.x); // error here
}
I would recommend defining an interface that declares the method that your multiple different types will expose. Something like:
public interface ValueProducer {
public String getValue();
}
Then, your Cube type would look like this:
public <T extends ValueProducer> void setPosition (T obj) {
System.out.println(obj);
System.out.println(obj.getValue());
}
Then any type with which you wish to use this method need only implement the interface ValueProducer, and can still extend or implement whatever other types are appropriate for their use cases.
Or, you could omit generics altogether, and just pass obj in as a ValueProducer.
your method does not know what is the type T.
But we can say T is some class which extends
public class GenericCube {
public String value;
}
So, now we able to access the value because we know about it
public <T extends GenericCube> void setPosition(T obj){
System.out.println(obj);
System.out.println(obj.value);
}
I found that I could access the field utilizing Reflection methods and cast to the object I needed. This is supported using an abstract class with this field so that all objects inheriting from this object can utilize this function.
public <T> void setPosition(T object) {
Field xField = object.getClass().getField("x");
Field boxField = object.getClass().getField("boundBox");
float xpos = (float)xField.get(object);
BoundingBox box = (BoundingBox)boxField.get(object);
}
I'm open to critique, but this has been working very well with my multiple classes inheriting from my abstract base class. The reason for this method, is for another class to work with these other classes without creating multiple functions, thus giving flexibility for a user who wants to create their own classes inheriting from the abstract class.
I have these interface and classes:
public interface AlternateLight {
public String change(long time);
}
public abstract class AbstractLight {
public String change(int time) {
return "AbstractLight Method was used";
}
}
public class DistinctAlternateLight extends AbstractLight implements AlternateLight {
public String change(long time) {
return "DistinctAlternateLight Method was used";
}
}
Now I call the method change() with following main-method:
public class WhatUsedTest {
public static void main(String[] args) {
AlternateLight al = new DistinctAlternateLight();
System.out.println(al.change(100));
}
}
It prints "DistinctAlternateLight Method was used", but why? I thought since I didn't put a "L" behind the 100 as argument, it would call the method of the abstract class, because its method takes integers. With missing out on the "L", I guessed the compiler wouldn't handle the 100 as a long value and call the method taking longs, but it does. Why is that so?
It's due to the polymorphism, if you declare your variable with AlternateLight class and this type has only acces to change(long time).
be careful. If you use interface as reference type and assign an object of implementing class to it then you can call only those methods that are declared inside the interface. This is quite obvious because the implementing class can define methods of its own that are not a part of the contract between the interface and class. So, to call those methods you have to use the class as reference type as following:
DistinctAlternateLight al =new DistinctAlternateLight();
The method with the closest match to your type arguments will be used.
But for compatible numerical, the deepest declared one.
You can also see that the type of "al" object is an interface type, so you can`t call the method from super class without casting, you also can`t call any method from AbstractLight without casting. You can only call methods there were declared in interface class. In that case, compiler will favour the method from the interface class.
You can force the compiler to call a method from abstract class if you write something like that:
System.out.println(((AbstractLight)al).change(100));
I haven't quite found an elegant way to solve this issue. I have an abstract class that several other classes are inheriting with an abstract method that can contain anywhere from zero to 4-5 arguments of varying types.
public abstract class Item {
public abstract void use();
}
For instance, I have a Book class that inherits this and takes no arguments when overriding use(), I have a Key class that inherits and takes a String and a Queue as arguments when overriding, etc...
I've tried using generics but I have to input the number used, such as Item, when it actually depends on the class.
public abstract class Item<T,U> {
public abstract void use(T arg1, U arg2); //Number of arguments/types could be more or less
}
I've tried sending a variable list of Objects but the object types are always variable and I've unsure as to the syntax to receive in the inheriting classes.
public abstract class Item<T> {
public abstract void use(T... arguments);
}
public class Book extends Item<?> {
public void use(?);
}
public class Book extends Item<String, Queue> { //Wrong number of arguments since I can't use Item<T...>
public void use(String str, Queue q); //fails
}
I may just be doing something wrong - can anyone offer any assistance or insight?
I've struggled with the same question, and there's not a perfect answer, but I can give you a few things to consider. First, you're basically trying to do something that is inherently against Object Oriented Programming, which is that you're trying to create a variable interface. The point of an interface is that code that gets an abstract version of the object (the Item rather than the Book, for example), knows how to invoke the use() method. This means that they must know what can be passed to the use() method. If the answer depends on the implementation of the abstract class or interface, then you need to ensure that the code using it actually knows what kind of implementation (Book, etc.) that it's using, otherwise it's not going to know how to invoke use() with the appropriate parameters anyway. It sounds like you need to refactor your code, in all honesty.
However, there is a way to answer your question as stated without refactoring the architecture. You could create a class that's data is all of the different types of parameters that could possibly be passed to the use() method, have the calling code set the fields of that class, and then pass that to the use() method. For example:
public class UseParameters {
private String string;
private Queue queue;
// Any other potential parameters to use(...)
public void setString(String string) {
this.string = string;
}
public String getString() {
return string;
}
// All of the other accessor methods, etc.
}
Then, you could define the use method in Item like this:
public abstract void use(UseParameters params);
And any code using an Item would have to set the parameters of the object appropriately:
Item item = // However you're going to get the item
UseParameters params = new UseParameters();
params.setString("good string");
params.setQueue(new Queue());
item.use(params);
I just want to point out that if the code above knows the Item is a Book (which is how it knows to set the String and Queue, then why not just get a Book and skip needing an abstract class with a variable use() method altogether? But I digress. Anyway, the Book would then implement the use() method like so:
#Override
public void use(UseParameters params) {
if(params.getString == null || params.getQueue() == null)
// throw exception
// Do what books do with strings and queues
}
I think that gets you what you want, but you should consider refactoring, I think.
What you want is the Value Object Pattern.
Define a class that encapsulates the various parameter types into one value object, and have the abstract method accept a parameter of this type. Each variation of parameters you were considering would have its own value class.
Then simply add a generic type to the class and have the abstract method accept a parameter of that type:
public abstract class Item<V> {
public abstract void use(V v);
}
To use it, suppose MyItem needs a value object of type MyValueClass:
public class MyItem extends Item<MyValueClass> {
public void use(MyValueClass v) {
}
}
If the types to be used as argument are always variable I don't see a reason to use generics. Just use plain Object type:
public abstract class Item {
public abstract void use(Object ... arguments);
}
public class Book extends Item {
public void use(Object ... arguments) { ... }
}
The best approach I can think of is to group the items according to the behavior of their use() method.
Example
public abstract class QueueableItem {
public abstract void use(String, Queue);
}
public abstract class OrdinaryItem{
public abstract void use(String);
}
If the grouped items share a common behavior (common as in same method signature & return value), you can define and extend a parent class that will contain the definition of this common behavior.
Yes, we can provide parameters to abstract method but it is must to provide same type of parameters to the implemented methods we wrote in the derived classes.
Here is my code want to access child class method of AdapterVer1 getAdaptObj1() (without type casting) using object reference of AdapterVersion (Parent class)
abstract class AdapterVersion {
public abstract void getMObject();
public abstract void getCObject();
}
public class AdapterVer1 extends AdapterVersion {
#Override
public void getMObject() {
System.out.println("AdapterVer1 Mont");
}
#Override
public void getCObject() {
System.out.println("AdapterVer1 Conf");
}
public void getAdaptObj1() {
}
}
public class AdapterFactory {
public static void main(String []a){
AdapterFactory adapterFactory= new AdapterFactory();
AdapterVersion adpater = adapterFactory.getMyObject("ver1");
adpater.getAdaptObj1(); // Unable to do that
((AdapterVer1)adpater).getAdaptObj1(); // Working but DONT WANT THIS
}
public AdapterVersion getMyObject(String version){
if(version.equals("ver1")){
return new AdapterVer1();
}else{
return new AdapterVer2(); // another declared class
}
}
}
You can't do that. Because at compile time, the compiler checks whether the method you invoked is accessible or visible in the class of the reference you are using or not.
So, in this case, since the reference is of Parent class, the compiler will look for the method declaration in the Parent class first in order to successfully compile the code.
Remember: -
Compiler is worried about the Reference type, and at runtime, the actual object type is considered, to decide which method to actually invoke.
The only option you have is to typecast, in which case, the compiler now looks into the class in which you typecasted the reference. Other option is, you can declare an abstract method with that name in Parent class, but from your question, it seems like you explicitly haven't done that.
You would need to move the method declaration to the abstract class.
Rohit already explained it beautifully. Just to add my 2 cents, you should first check the subclass type and then typecast, for instance:
if(adapter instanceof Adapterver1) {
((AdapterVer1)adpater).getAdaptObj1();
}
This way your code will be safer if it tries to handle a new subclass which doesn't declare such method.
But the question you must ask, if you already know what subclass method to call, why accessing it from superclass reference?
First things first, please be aware I am trying to express my question as best I can with my current knowledge and vocabulary, so please excuse this...
I have an abstract class in which I want to make a method where it instantiates itself.... Of course this is impossible in an abstract class, however, what I really want is for the concrete children (those classes that "extends") to inherit this instantiation so that they then can instantiate themselves....
Basically what I want to do is this:
MyAbstract a = new this();
However this isn't allowed... Is there any way I can do what I want?
Here is some non-compiling dream-code (i.e. code I wish worked). Basically I am wanting the ConcreteChild to call a method in which it create an object of itself. The method is inherited from it's parent.
public class Abstract {
public void instantiateMyConcreteChild()
{
Abstract a = new this();
}
}
public class ConcreteChild extends Abstract{
public static void main(String[] args) {
ConcreteChild c = new ConcreteChild();
c.instantiateMyConcreteChild();
}
}
* Additional info **
Thanks for the replies but I think I missed something vital....
Basically I wanted to pass an object's self ( "this" ) into some methods of some other classes. However, creating instantiating another object within an object is a bit backwards, I can just pass "this", right...
You can do this using reflection, something like :
Abstract a = getClass().newInstance();
This is because getClass() always returns the concrete class, so this.getClass() will return the real subclass and not the current class.
However, beware that if the subclass defines a custom constructor, having more or less parameters than your abstract class, it could fail. Unless you specify in the documentation that subclasses must have a constructor with such given parameters ... but it's fragile anyway.
You can inspect it, using getClass().getConstructors() and see which constructors are there, and if there is the one you are expecting, or even search for a viable one, otherwise you can catch the exception thrown by newInstance(..), and wrap it in a more descriptive exception for the users, so that they understand better what they missed ... but it would still be a kind of a hack, cause there is no explicit language support for such a situation.
Another approach could be to implement Cloneable in your abstract class, and then use the clone method, but it could be overkill or even wrong if what you want is a new, clean instance.
You can't do this using an instance method. Because as the name implies an instance methods requires that the instance has already instantiated.
What you actually need to do here is to separate the non-changing internal functionality from the abstract class itself. So what I could do is to ,for e.g., have an inner class that really encapsulates the non-changing functionality like so:
public class Abstract {
public void instantiateMyConcreteChild()
{
Abstract a = new NonChangingOperations();
}
class NonChangingOperations
{
public void operationA() {}
}
}
Infact you really dont need to keep the class NonChangingOperations as an inner class, you could make it as an external utility class with its own class hierarchy.
Are you trying to define a constructor that the subclasses of Abstract can use? If so you could simply do it the same way you define any other constructor.
public class Abstract {
Abstract() {
//set fields, etc. whatever you need to do
}
}
public class ConcreteChild extends Abstract{
ConcreteChild() {
//call superclass's constructor
super();
}
}
Could you just have this ?
public abstract class AbstractClassWithConstructor {
public AbstractClassWithConstructor() {
init();
}
protected abstract void init();
}
FYI
In the objective-c you need to set this by calling method init. The the method init() would look like this:
protected AbstractClassWithConstructor init() {
return this;
}