I would like to make copy of SubClass object in BaseClass constructor. I need that the following code execute correctly.
class BaseClass{
BaseClass() {}
BaseClass(BaseClass base) {
//TODO: how to implement?
}
}
class SubClass extends BaseClass {
SubClass() {}
}
public class Test {
public static void main(String[] args) {
BaseClass sub = new SubClass();
BaseClass subCopy = new BaseClass(sub);
if (subCopy instanceof SubClass) {
// need to be true
}
}
}
Is it even possible? If yes how can I do it? Else how can I get similar effect?
It's not possible. A constructor of class A gives you an instance of A, no way to circumvent this. Why not instantiate the subclass explicitly?
Another possibility might involve a static factory method like:
public static BaseClass create(BaseClass input) {
// return BaseClass or subclass
}
It seems like you want the object of BaseClass to be an instance of SubClass which extends BaseClass.
Is it even possible?
-No. It is not possible.
The instanceof operator returns true if the variable on left side satisfies IS-A condition of the variable or class on the left side.
The SubClass IS-A BaseClass since it extends BaseClass. But the BaseClass can never be a SubClass, since it can't extend SubClass.
You seems to be having a design upside-down. If you need to do what you are asking then you need to re-think over your design. Ideally in your subclass constructor, you should be copying or initializing the base class properties by calling super().
Related
I want to call this.getClass() before calling the constructor with super(...).
abstract class A extends SuperClass {
public A() {
super(Manager.someOtherMethod(this.getClass()))
// Does not work: "Cannot reference 'Object.getClass()' before
// supertype constructor has been called".
}
}
I read about a workaround using static methods, but this.getClass() cannot be called from a static context.
This question depends on my previous question.
Thanks in advance for you answers :)
Whilst I am dubious about the need for this, you can do it by inserting the call to Manager.someOtherMethod into the constructor of the superclass:
class SuperClass {
SuperClass() {
Object result = Manager.someOtherMethod(this.getClass());
}
}
class A extends SuperClass {}
class Manager {
static Object someOtherMethod(Class<?> clazz) {
System.out.println(clazz);
return new Object();
}
}
would print out
class A
(if you create an instance of A)
Ideone demo
If SuperClass has multiple constructors, you can assign the result to a field in the superclass:
class SuperClass {
private final Object result = Manager.someOtherMethod(this.getClass());
SuperClass() { ... }
SuperClass(String someParameter) { ... }
}
then result will be available in both constructors.
I suggest you to refactor your code.
I assume that you have classes A1, A2 and A3 now.
You should introduce factory like this:
class AFactory {
public static A1 newA1() {return new A1(A1.class);}
public static A2 newA2() {return new A2(A2.class);}
public static A3 newA3() {return new A3(A3.class);}
}
Add parameter to classes A1, A2 and A3 constructors.
Add parameter to A constructor.
...what's the question? Do I understood correctly, do you want the class to be subclassed, and THAT class should be given to the super, but you don't want to call super in all the subclasses?
Indeed it can't be done this way as the class object is not constructed yet, and therefore it does not exist. So you cannot call a method on the object yet, or ask for the name, or whatsoever.
I think you're stuck with either a class passing on to super, or add a pretty useless public static class<? extends SuperClass> getThisClass() { ... } or am I missing something nice? if I do, pls comment, as I actually like to know myself too.
Just for curiousity I tried different ways which are stated here: Getting the class name from a static method in Java but the closest I got was getting that class test.staticgetclass.A in the middle class, but never its subclass name which I think you want to get.
Use a class literal as a constructor parameter
abstract class A extends SuperClass {
protected A(Class<? extends A> clazz) {
super(Manager.someOtherMethod(clazz));
}
Then in impl:
class B extends A {
public B() {
super(B.class);
}
Okay, so recently I realized that I have some misunderstandings with extending and inheritance inside of java.
So far, my understanding states that you cannot do this
MySubClass myClass = (MySubClass) new MyClass();
That makes enough sense to me, but there are a few gabs and work-arounds that I don't know how to succeed in, such as if a person is trying to get a SubClass from a method that returns the SuperClass. For example:
public static MyClass getNewMyClass() {
return new MyClass();
}
And inside of MySubClass there are specific methods I want to access, such as
public void sayBye() {
System.out.println("Bye.");
}
So what I would think is I need to do is
((MySubClass) myClass).sayBye();
..but of course that throws a ClassCastException.
Summary/Question
So basically my question will be, how do I get the subclass of a returned class from a method, or is it possible?
Example: MyClass.getNewMyClass() returns a new MyClass, but I want to use the method sayBye() in its subclass, MySubClass.
More Information
The reason I'm asking this is because I'm trying to create an API for myself that basically will shorten the development of what I am trying to accomplish. In one of my classes, it contains a whole bunch of methods that returns MyClass. Some method examples could be public MyClass getNewMyClass() {}, public MyClass findMyClass(String name)() {} and so on.
But when I get to exending MyClass for some extra methods, I have about 10 methods from the superclass that returns MyClass, and all of that basically will leave me back to the beginning. Is there the possibility of returning Class<? extends MyClass> instead, or something similar?
Solved
Thank you everyone so much for your help, it is very much appreciated! So I basically decided to go with delegation. To solve my issue, here were all of my code and classes, that allowed me to access the superclass, but return the subclass.
Here was my InheritanceTest.java
public class InheritanceTest {
public static void main(String[] args) {
MyClass myClass = MySubClass.doMath();
if (myClass instanceof MySubClass) {
((MySubClass) myClass).sayBye();
}
}
}
And my MyClass.java
public class MyClass {
protected String name;
public MyClass(String name) {
this.name = name;
}
public String getName() {
return name;
}
public static MyClass getNewMyClass() {
return new MyClass("Toshimaru");
}
public void sayHi() {
System.out.println("Hi.");
}
}
And finally, where it all seems to be resolved, MySubClass.java
public class MySubClass extends MyClass {
public MySubClass(String name) {
super(name);
}
public static MySubClass doMath() {
// Got the new instance of MyClass
MyClass myClass = getNewMyClass();
// And turned it into a MySubClass with myClass' properties.
myClass = new MySubClass(myClass.getName());
return (MySubClass) myClass;
}
public void sayBye() {
System.out.println("Bye.");
}
}
The trouble with trying to get a subclass from a superclass is you don't know what subclass it is. You could do an instanceof check first before casting and that would avoid the ClassCastException, but that is nasty. Ideally you should have your methods return objects that are as high up the hierarchy as possible but if you need a method that belongs to a subclass then that should be the return type of the method.
EDIT:
Your more information is a little vague, but this is legal:
public class MyClass {
public MyClass getNewMyClass(){
return new MyClass();
}
}
public class MySubClass extends MyClass{
#Override
public MySubClass getNewMyClass() {
return new MySubClass();
}
}
You can't make an Animal to bark, Only a sub class of Animal, Dog can bark.
In the same way, You can't invoke a sub class method on super class instance. Object oriented concepts are very much similar to real world.
MySubClass is an acceptable return for MyClass. I would instead return new MySubClass() which would then be able to call the subclass method. Polymorphism applies.
All Toyotas are Cars, but not all Cars are Toyotas. How does this relate here? In this example, Car is analogous to your MyClass and Toyota is analogous to your MySubClass.
If you create an object as a Car, you won't have access to the methods inside Toyota. However, if you create an object as Toyota, you do have access to the public (or protected) methods inside Car.
If you're the designer of MyClass and MySubClass, and you think sayBye() is a method that should be accessible at the parent level, then maybe you need to consider redesigning/refactoring and making sayBye() a method in your parent class.
This cast:
((MySubClass) myClass).sayBye();
does NOT always throw a ClassCastException, as you said, but it depends on what is the actual (more specific) type of the object referenced by the variable myClass.
If the variable MyClass myClass references an object of the class MySubClass, then the cast does not throw any exception.
But the point is that, if you want to call a method of an object, this method must be defined and implemented in the class (or some superclass) of that object, while you can NOT call a method on a object, where this method is only implemented in some of its subclass, because in this case that method is not present in that object (but only on object of its subclass).
I have a superclass, let's say BaseClass and two subclasses, let's say SubclassA and SubclassB, they don't have any other relationship between them but their parent class.
At a lot of places in my code I need to call to methods that both the subclasses have but not the parentclass... And I find myself repeating a lot of code which looks like:
if (obj instanceof SubclassA) {
// stuff
} else if (obj instanceof SubclassB) {
// same stuff
}
The first idea should be to put that "stuff" into a method in superclass, but I can't as that superclass is parent to other subclasses that don't have that behavior...
So... is there a way to avoid repeating aaaalll of that code?
Maybe a common superclass for both subclasses that is a subclass itself of superclass?
I would suggest extracting the method as an abstract method in the parent(if the parent is abstract), or just a method that will be overridden in child classes. If this is not possible, or desirable I would suggest adding a common abstract class that extends the parent that has just the method that is common to both subclasses, that will be then extended by the two subclasses.
If adding and changing the parent class might be an issue, you can do the same thing by using an interface that is then implemented by both subclasses and where you need to call your code you will just cast to the given interface and call the needed method.
Something like this:
interface CommonInterface {
void commonMethod();
}
class SubClassB implements CommonInterface {
void commonMethod() {
// implementation
}
}
class SubClassA implements CommonInterface {
void commonMethod() {
// implementation
}
}
//...
if (obj instanceof CommonInterface) {
((CommonInterface)object).stuffCall();
}
Add the method to the super class.
Make it with an empty body.
In SubClassA override it, implement the logic you need.
In SubClassB override it, implement the logic you need.
Then in your calling code, instead of doing
if (obj instanceof SubclassA) {
obj.method();
} else if (obj instanceof SubclassB) {
obj.method();
}
just do this
obj.method();
provided obj is declared as an instance of the parent class.
The empty method body in the super class guarantees you have
no issues with this "but I can't as that super class is parent
to other subclasses that don't have that behavior".
So the idea is that you will have empty behavior
in the super class and in all the sub classes which
do not explicitly override this method.
Firstly, the concept of polymorphism is to do away with the need to check the type of an object before calling methods on it. So, this should not be necessary in an OO-language.
Secondly, the reason why you might use an abstract parent class over an interface would but because there is some shared functionality between sub-types (subclasses). So, if there is shared, common functionality between SubclassA and SubclassB then leave your superclass intact, otherwise switch it to an interface.
Likewise, and as you suggest yourself, if SubclassA and SubclassB have a common behaviour (but their own implementation) then utilise a separate API (if other sub-types of BaseClass do not also share that behaviour (your #doStuff call).
In this case, I'd introduce interface Stuff containing method #doStuff and have both my SubclassA and SubclassB implement it, each providing it's own implementation. Your clients can then treat your obj instance as a Stuff, irrespective of it's real type and polymorphism will do the rest.
interface Stuff {
void doStuff();
}
public class SubclassA extends BaseClass implements Stuff {
// Does it need BaseClass still?
public doStuff() {
...
}
}
public class SubclassB extends BaseClass implements Stuff {
// Does it need BaseClass still?
public doStuff() {
...
}
}
// Example client code...
public class MyStuffClient {
Stuff s = new SubclassA();
...
public void onStuff() {
s.doStuff();
}
}
Decide if you really need the suer class BaseClass.
What about the following two ways:
Declare the target method in super class and provide a default implementation(e.g. empty method, do nothing) as well. Subclass will override that behavior if needed.
Declare the target method in a Interface, and make SubclassA and SubclassB implementation of the interface. The super class and other subclasses don't need to implement the interface.
If SubClassA and SubClassB have some behaviour that isnt present in Subclass C, D, E etc then just introduce an intermediate class between the parent and A and B. C, D etc derive from the parent, And B derive from the new class, which contains functionality that A and B share.
You can make the method on the superclass protected. For example, you can do this on SuperClass:
package test;
public SuperClass {
protected void myMethod() {
...stuff...
}
}
exposing on SubclassA
package test;
public SubclassA extends SuperClass {
public void myMethod() {
super.myMethod();
}
}
and hiding on SubclassB (just not override it)
package test;
public SubclassB extends SuperClass {
}
From a different package, protected methods are not visible unless the class override it changing its visibility modifier.
Source: http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
I have the following classes.
public class Super{
public static void useSubClass(){
//I want to access the sub class object here, how.
}
}
public class Sub1 extends Super{
}
public class Sub2 extends Super{
}
I want to access the sub-class object from a static method in super-class. i.e. When I call Sub1.useSubClass() the method has access to Sub1.class and when I use Sub2.useSubClass(), I can access the Sub2.class.
Is there any way to access the sub-class object from super-class.
In general, you cannot do that from a superclass (and shouldn't!) because you won't know (and shouldn't assume anything about!) what classes will inherit from your superclass.
Depending on exactly what you want to do, there are alternatives, such as:
Use the template pattern to define "filler methods" that your subclasses must implement; these filler methods will be called by the template method in your superclass.
Define methods to be overridden by your subclass.
Define interfaces to be implemented by your subclass.
Update: As #JB Nizet has pointed out, I might have misread the question.
Here's something (very similar to the Observer Pattern) you can do if you wish to access subclasses from the static method in your superclass:
Define a static listener list in your superclass, call it List observerList
In the constructor of your superclass, add the class instance itself to that static observerList
For all subclasses, it is their responsibility to call super() from their constructors in order to register themselves to observerList (and unregister in deconstructor)
Then in your superclass's static useSubClass() method, you can iterate through that list of subclass instances, find the particular one you care about (maybe specified by some argument), and then do something with it.
Static methods are not inherited, and calling Sub2.useSubClass() is strictly equivalent to calling Super.useSubclass().
There is no way to get this information, because it doesn't exist. The compiler allows calling Sub2.useSubclass(), but translates it into Super.useSubclass().
public static void useSubClass(Super sub) {
if (sub instanceof Sub1) {
// Do something
} else if (sub instanceof Sub2) {
// Do something else
} else {
// Something else is extending Super
}
}
However, a better question is why? Can't you simply override the method in your subclass?
No you cannot because the super-class cannot know the methods of the sub-classes.
You should consider to create a new class which sees both super-class and sub-classes and implement the static method inside this new class
For the record, you could do this in Python, using class methods:
class super(object):
#classmethod
def usesubclass(cls):
print cls
class sub1(super):
pass
class sub2(super):
pass
Using this code, you could call sub1.usesubclass() or sub2.usesubclass(), and that would print the representations of the sub1 and sub2 classes, respectively:
>>> sub1.usesubclass()
<class '__main__.sub1'>
>>> sub2.usesubclass()
<class '__main__.sub2'>
Java, however, does not support such mechanisms, unfortunately. When you compile Sub1.useSubClass() in your example, the compiler will simply use Sub1 as the basic namespace to look up the the useSubClass() method in Super, but no information on that is actually compiled into code. In the resulting bytecode, the call is simply one directly to Super.useSubClass() and nothing more.
I sympathize with your plight, but Java is what it is. The closest thing you could come, I think, would be the following code:
public class Super {
public static <T extends Super> void useSubClass(Class<T> sub) {
}
}
And then call that method explicitly as either Super.useSubClass(Sub1.class) or Super.useSubClass(Sub2.class).
I figured something out. It works if implemented with care.
/** SuperClass.java **/
public abstract class SuperClass {
public static void printClass(){
System.out.println(new ImplementingClassRetriever().getCallingClass());
}
static class ImplementingClassRetriever extends SecurityManager{
public Class getCallingClass() {
Class[] classes = getClassContext();
for (Class clazz : classes) {
if (SuperClass.class.isAssignableFrom(clazz) && clazz != null
&& !clazz.equals(SuperClass.class)) {
return clazz;
}
}
return null;
}
}
}
/** Main.java **/
public class Main{
public static void main(String[] args) {
Sub.printClass(); //this does not work
Sub.testStaticCall(); //this works!! :)
}
}
class Sub extends SuperClass{
public static void testStaticCall(){
Sub.printClass(); //calling the method in the super class
}
}
This is just a toy example. The super class contains a static class that contains a method to retrieve the calling class.
In the subclass I have another static method which calls the superclass's method for printing the class name.
The Main class/function contains two calls to Sub's inherited and locally implemented method. The first call prints null, because the calling context (i.e. Main) is not a subclass of Super However the delegate method in Sub works because the calling context is now a subclass of SuperClass and hence the calling class can be determined.
Although You can create a reference to the super class and point it to any sub-class. This can also be done dynamically during run-time. This is a way of run-time polymorphism.
I have 3 classes, MainClass with main method, one abstract class named AbstractClass and Subclass which is to be extended with AbstractClass.
The array of objects is created in main method from type AbstractClass containing 1 member.
Then I initialize that 1 element of array as type Subclass( is this ok?).
The problem is I can't get to the getDataToExport() method of created object ( array[0] ) .
I suspect the problem occurs because the array is the AbstractClass type...
And the question: is this even possible to accomplish?
What I'm trying to do is use an array of type AbstractClass and fill it with objects made from different subclasses( in this code is just one->Subclass ) extended with AbstractClass but i can't get to the methods of that subclasses.
main class with main method
public class MainClass {
public static void main() {
AbstractClass array[]=new AbstractClass[1];
array[0]= new Subclass(); // is this even allowed?
System.out.println(array[0].getDataToExport()); // Problem!
}
}
abstract class
public abstract class AbstractClass {
}
Subclass which extends AbstractClass
public class Subclass extends AbstractClass {
private int dataToExport;
public Subclass(){
this.dataToExport=2;
}
public int getDataToExport() {
return dataToExport;
}
}
AbstractClass array[]=new AbstractClass[1];
array[0]= new Subclass(); // is this even allowed?
Yes, that's fine, but it means that when you later go to use it, you only have access to what's defined in AbstractClass (barring using a cast, but you want to avoid using casts wherever you can, and there's no need for one here).
The only real reason for making the array entries of type AbstractClass would be if you only want to interact with the members defined in that class. So for instance, in this case, you'd probably want to have the getDataToExport defined as an abstract method in the abstract class:
public abstract class AbstractClass {
public abstract int getDataToExport();
}
You might also consider looking at having an interface rather than an abstract class. Since a class can only derive from one base class, but can implement as many interfaces as it likes, unless there's a large body of common implementation that you'd be putting in the abstract base class, you're better off with an interface — because it doesn't put unnecessary constraints on the implementations of that interface. In fact, you're almost always better off with an interface; you can always also have an abstract base if you want.
So for instance:
public class MainClass {
public static void main() {
NiftyThingy array[]=new NiftyThingy[1];
array[0]= new NiftyThingyImplementation();
System.out.println(array[0].getDataToExport());
}
}
where
public interface NiftyThingy {
public int getDataToExport();
}
and
public class NiftyThingyImplementation implements NiftyThingy {
public int getDataToExport() {
return /* ... the data ... */;
}
}
You must declare getDataToExport() as an abstract method in AbstractClass.
You won't be able to get it because you are declaring an array of AbstractClass in order to see them you have two choices
Declare the common methods that you will use on the abstract class and declare them abstract. Override those methods in the subclasses. For example:
public abstract class AbstractClass {
public abstract int getDataToExport();
}
And every subclass will have to override that method or should be declared abstract too.
Create an array of Sublclass:
Subclass array[] = new Sublcass[1];
array[0] = new Subclass();
System.out.println(array[0].getDataToExport());
Yes, all this is perfectly fine. The only step you have missed is that you need to cast the instance of the object to the type that has the method you want. The usual way to do this is:
AbstractClass ac = array[0];
if (ac instanceof Subclass) {
System.out.println(((Subclass)ac).getDataToExport()); // No problem!
}
However you might want to think about doing this another way. For example, implement a default version of getDataToExport in the abstract class that returns null. That way you don't have to do the cast or the instanceof test.
AbstractClass array[]=new AbstractClass[1];
array[0]= new Subclass(); // is this even allowed?
Indeed is valid as SubClass is a derived class of AbstractClass. The reason why
System.out.println(array[0].getDataToExport());
fails is because the compiler cannot find AbstractClass.getDataToExport() method. It's only SubClass that has the method and not its parent.
There are couple of ways to solve this:
Add an abstract method getDataToExport to the AbstractClass like so:
public abstract class AbstractClass {
public abstract int getDataToExport();
}
OR, Typecast your variable to its derived (concrete) class that has the getDataToExport() method, like so:
if (array[0] instanceof SubClass) {
System.out.println(((SubClass)array[0]).getDataToExport());
}
the instanceof operator simply states that the attribute is of a class X (where X is SubClass).