Accessing subclass methods within a vector of of superclass objects - java

I am using a vector to store objects of an abstract superclass. I need to access a method(s) within the derived subclasses of each object in the vector. I will be using instanceof in order to differentiate which subclass each object is a part of.
I do not have permission to write to the abstract class.
Currently the compile error I am getting is:
Error: cannot find symbol
symbol: method <mySubclassMethod>()
location: class <MyAbstractClass>
What is the most effective way of going about accessing the subclass methods of each object within my vector?

You need to cast the object to the subclass inside of an instanceof guard.
if (obj instanceof MySubclass)
((MySubclass)obj).mySubclassMethod();
More broadly, if the method should be available in all of your subclasses, you should add it to the abstract superclass. Then, when you call the method on the 'uncasted' abstract superclass object, it will use the implementation from the proper subclass.
public abstract class MySuperclass {
public abstract void mySubclassMethod();
...
}
public class MySubclass extends MySuperclass {
#Override
public void mySublcassMethod() { ... }
...
}
...
MySuperclass obj = [actually a Subclass];
obj.mySubclassMethod(); // uses the implementation from MySubclass

I think what you want to do is to create the method as abstract in your superclass. Then, what you will do is override this method in each of your subclasses. This will allow you to access that method for all the different objects in that vector of yours.
I'm assuming this method will vary depending on your subclass, otherwise, why wouldn't you just write that method in the superclass in the first place.

Related

Java uninitialised constants in an abstract class

I am writing an abstract class. The classes that extend this class will always use the constant A_CONSTANT, but the value of A_CONSTANT is different for each subclass. The subclasses will also implement the method useConstant. This implementation will be the same for each subclass, other than the value of A_CONSTANT will be different. Preferably I would like to implement useConstant in the abstract class, but an error is produced because A_CONSTANT has not been initialised in the abstract class.
public abstract class AbstractClass {
public static final int A_CONSTANT;
public void useConstant(int value) {
if (value > A_CONSTANT)
// do something
}
}
Is there any way around this, or will I have to provide the implementation of useConstant in each of the subclasses?
You can have an abstract method getConstant, then all the subclasses will have to implement it

java Generics - How to call child overloaded method knowing the child class type and the superclass

I have a bunch of classes that extend a base class. The base class has a method shall we say :
doStuff1(int variable){ do something;}
Each of these classes have a :
doStuff1(String string) {convert string to number and call super.doStuff1(intResult)};
In another class, method I have something like:
public void bla(Class<?> childClass, SuperClass childClassInDisguise) {
(childClass.cast(childClassInDisguise)).doStuff1(myString);
}
I cannot compile this because of:
The method doStuff1(myString) is undefined for the type capture#17-of ?
What am I doing wrong here ?
Is this even possible ?
Thanks.
The compiler don't know which class this represents to,
Class<?>
and the only clue it knows with regards to the object is that it has a superclass which only have doStuff1(int)
If you really want to call the doStuff1(String), why not create another abstract subclass that contains this method and marked this method as abstract. The existing subclasses should extend this new subclass.
public abstract class NewSubclass extends Superclass {
public void abstract doStuff1(String);
}
Then in your method, add a generic parameter such as
public <T extends NewSubclass>void bla(Class<T> childClass, SuperClass childClassInDisguise) {
(childClass.cast(childClassInDisguise)).doStuff1(myString);
}
This way, the compiler knows the inheritance heirarchy of the object which are subclasses of the NewSubclass that contains that abstract method.
EDIT
If you can only edit bla method, try this,
public void bla(Class<?> childClass, SuperClass childClassInDisguise) {
if(childClass.equals(ChildClass1.class) {
(ChildClass1(childClassInDisguise)).doStuff1(myString);
} else ... {
}
}
Do the same if condition in other known subclasses. I know its hardcoded, but this is the only way if you can't use generic + abstract superclass by modifying those classes involved. But I still prefer my first suggestion since its less code and dynamic, like when you add another subclass, you don't have to change bla method again(the power of POLYMORPHISM), unlike the second suggestion. This is more of a design reconstruction issue.

Invoke a method of a class which is implemented in her supperclass

I have a class java ProductManager which extends another class with the same name,
located in another project with another package("com.services") .
I have to invoke a method deleteProduct(Long productId) located in the super-class.
try{
Object service = CONTEXT.getBean("ProductManager");
Method method = service.getClass().getDeclaredMethod("deleteProduct", Long.class);
method.invoke(service, productId);
} catch(Exception e){
log.info(e.getMessage());
}
I couldn't delete the product:
I get this info:
com.franceFactory.services.ProductManager.deleteProduct(java.lang.Long)
the product isn't deleted :(
The various getDeclaredMethod() and getDeclaredMethods() only return methods declared on the current class instance. From the javadoc:
This includes public, protected, default (package) access, and private methods, but excludes inherited methods.
The important part here is "but excludes inherited methods". This is why you are getting an exception with your code as it currently stands, it is not returning the deleteProduct() method from the parent class.
Instead if you wanted to continue using reflection you would need to use the getMethod method as this returns all public methods, "including those declared by the class or interface and those inherited from superclasses and superinterfaces."
If you have to use reflection then don't use getDeclaredMethod() because (as its name suggest) it can return only methods declared in current class, while you claim you want to invoke method declared in other class (to be precise declared in super class).
To get public method (including also inherited ones) use getMethod().
If your are overriding that method, just use the reserved word super (from the Oracle documents):
public class Superclass {
public void printMethod() {
System.out.println("Printed in Superclass.");
}
}
public class Subclass extends Superclass {
// overrides printMethod in Superclass
public void printMethod() {
super.printMethod(); // This calls to the method defined in the superclass
System.out.println("Printed in Subclass");
}
public static void main(String[] args) {
Subclass s = new Subclass();
s.printMethod();
}
}
This code will write:
Printed in Superclass.
Printed in Subclass
In other case (you are not overriding it, just using it), just write this.methodName(...). All methods inherited are directly available.
Disclaimer: I am not sure I totally understand your question. I will still try to answer what I think I understand.
The Product in package com.franceFactory.services (Lets call it A)
extends The Product class in package com.services (Lets call it B)
So A extends B.
B has method deleteProduct(java.lang.Long)
A overrides the method deleteProduct(java.lang.Long)
You have instance of Class A. So by OOPS concept method deleteProduct of object A is going to get called.
There is no way you can call the super method from outside unless you have the instance of class B.
EDIT
OPs Clarification yes, it's public, but it isn't overridden in my class
The method in super is getting called here. The product is not getting deleted for reason on what is written on the method.

Using subclass' method in superclass

I have a class (called SubClass for simplicity) that extends SuperClass and implements IClass.
I know that you can call SuperClass' methods by using super.method(), but is it possible to call a method from SubClass which it implements from IClass?
Example:
public class SuperClass {
public void method(){
implementedMethod();
}
}
Subclass:
public class SubClass extends SuperClass implements IClass{
public void implementedMethod() {
System.out.println("Hello World");
}
}
IClass:
public interface IClass {
public void implementedMethod();
}
I would like to call SubClass' implementedMethod() (Which it gets from IClass) from SuperClass
How would I go about doing that?
You can make the super class abstract:
public abstract class SuperClass implements IClass {
public void method(){
implementedMethod();
}
}
Given the types above, anExpressionOfTypeSubClassOrIClass.implementedMethod() must be used. Note that the Type of an expression - the view it provides - must have the method intended to be used. In this case, an expression of type SuperClass cannot be used here because it has no declared implementedMethod member.
One approach - and arguably the preferred approach - is to use abstract methods. Even though abstract methods are not strictly required for Polymorphism they describe scenarios such as this where a subclass should provide the implementation. (The abstract methods could be replaced with empty method expecting - but not requiring - to be overridden in sublcasses, but why not use abstract for its designed purpose?)
abstract class SuperClass implements IClass {
// Don't implement this, but declare it abstract
// so that we can conform to IClass as well
public abstract void implementedMethod();
public void method () {
// Now this object (which conforms to IClass) has implementedMethod
// which will be implemented by a concrete subclass.
implementedMethod();
}
}
This has the "negative" aspects that SuperClass cannot be directly instantiated (it is abstract, after all) and that SuperClass must implement (or, as shown, delegate out via abstract) the expected signature. In this case I also chose to make SuperClass implement IClass even though it's not strictly required because it guarantees that the SuperClass and all subclasses can be viewed as an IClass.
Alternatively, remember that Types of Expressions are just views of objects and are not necessarily the same as the actual Concrete Type of object. While I would advise against using the following code because it loses some type-safety, I think it shows the important point.
class SuperClass {
public void method () {
// We try to cast and NARROW the type to a
// specific "view". This can fail which is one
// reason why it's not usually appropriate.
((IClass)this).implementedMethod();
}
}
class SubClass extends SuperClass implements IClass {
// ..
}
class BrokenSubClass extends SuperClass () {
}
// OK! Although it is the SAME OBJECT, the SuperClass
// method can "view" the current instance (this) as an IClass
// because SubClass implements IClass. This view must be
// explicitly request through a cast because SuperClass itself
// does not implement IClass or have a suitable method to override.
(new SubClass()).method();
// BAD! ClassCastException, BrokenSubClass cannot be "viewed" as IClass!
// But we didn't know until runtime due to lost type-safety.
(new BrokenSubClass()).method();
The only way to call that method would be to create an object of type SubClass (in SuperClass) and call subClassInstance.implementedMethod().
I also want to stress that this is very inelegant. As stated in a comment on your question, you should reconsider your class designs if your superclass needs to call a subclass method.

abstract classes which implements an incomplete interface

For example, I have an interface with 4 methods.
If I implement this interface incomplete in a class, the class must be abstract. Right?
For example, I leave one method out. So now I am writing a subclass which extends this class. Now I implement the last method of the interface.
What happens, if I call this method in the abstract superclass? Nothing! It works. But why?
What will happen, if I write several classes, extending this abstract class and implement the fourth method of the interface? Which one will be called?
A interface is a contract you define the signature of your methods, only behaviour and constants, all methods are public and abstract.
In an Abstract Class you define behaviour and state, you can have some implementation and abstract methods.
For example for your question:
If I implement this interface incomplete in a class, the class must be
abstract. Right?
Right
For example, I leave one method out. So now I am writing a subclass
which extends this class. Now I implement the last method of the
interface.
What happens, if I call this method in the abstract superclass?
Nothing! It works. But why?
Will run cause in runtime execution knows what class is. this is polymorphism.
What will happen, if I write several classes, extending this abstract
class and implement the fourth method of the interface. Which one will
be called?
The one you instanciate in your client code :D
public interface Operation{
void operation1();
void operation2();
}
I don't implement operation2
public abstract class ClaseBase implements Operation{
//with final im saying childs wont override
public final void operation1{
// do something
operation2();
// do something
}
}
//have to implements operation2 cause it's a concrete class
public class Child extends ClaseBase{
void operation2(){
System.out.println("Something");
}
}
You can't instanciate an AbstractClass.
In your client code
ClaseBase base = new Child();
base.operation1(); // and it's gonna to call operation2 in childClass
Abstract class is useful with Template Method pattern.
It depends on the object that you created. Super class can refer to subclass objects. So the actual object's method would be called.
interface A{
public void test1();
public void test2();
}
public abstract class B implements A{
public void test1(){
}
public abstract public void test2();
}
public class C extends B{
public void test2(){
}
}
B b = new C();
b.test2();//This works because the object that is refered by B is actually an object of C
Infact you can also do:
A a = new C();
a.test1();
a.test2();
Again though A is an interface(super type), but it is actually referring to a concrete implementation C(subtype) object and hence this works.
So at the compile time, compiler checks if A/B has a method called test2(), if yes compile is happy and it compiles successfully. But at the runtime, you invoke test2() method on the object and object actually is of class C which has the complete implementation.
Keep in mind that when you instantiate a subclass and refer it as super/abstract class or interface, it's still the instance of the subclass. Any method called on the object bubbles up from subclass to super class if its not available in the sub class.
Thus if you have:
interface GemeInterface
getStartScreen()
getCloseScreen()
abstract class AndroidGame implement GemeInterface
getCloseScreen()
class MrNomGame extends AndroidGame
getStartScreen()
class MrPetNomGame extends AndroidGame
getStartScreen()
and using as
//You can't instantiate AndroidGame hence the it has to be instance of a subclass
AndroidGame androidGame1 = new MrNomGame ();
androidGame1.getStartScreen();
//You can't instantiate AndroidGame hence the it has to be instance of a subclass
AndroidGame androidGame2 = new MrPetNomGame ();
androidGame2.getStartScreen();
Then also it works as androidGame1.getStartScreen() --> calls the method from MrNomGame, while androidGame2.getStartScreen() --> calls the method from MrPetNomGame.
Both the calls i.e. androidGame1.getCloseScreen() and androidGame2.getCloseScreen() will end up calling the method from AndroidGame as it's not available in the sub classes.
What happens, if I call this method in the abstract superclass? Nothing! It works. But why?
You cannot invoke this method on the abstract superclass because it can't be instantiated. You would only be invoking it on a sub-class of this abstract super-class which would be forced to provide an implementation (or be declared abstract itself).
So, when you invoke this method, its the implementation provided by the non-abstract sub-class that gets executed.
The funny thing is that a method of the class 'AndroidGame' calls 'getStartScreen()'. But there could be several classes like 'MrNomGame' which extending 'AndroidGame'. Then which method would be executed?
The method code executed would depend on the runtime type of the actual object that you invoke this method on. So, you could have a code like this
AndroidGame game1 = new MrNomGame();
AndroidGame game2 = new SomeOtherGame();
game1.getStartScreen(); // invokes MrNomGame's version
game2.getStartScreen(); // invokes SomeOtherGame's version
and due to dynamic binding the JVM would invoke the getStartScreen() as implemented by the class type of the actual object that the reference points to.

Categories