Firstly, sorry for the poor English, it is not my first language
How would one go about creating a object of a type from a subclass via the super class.
e.g.
if I have a super class:
public class superClassName(){
method(){
make object of subclass type used
}
and then I call the method in a subclass.
I'd like to have a an object created based on the subclass that's been called if that makes sense?
Using reflection may provide the quickest solution (this.getClass() returns the concrete subclass):
void method(){
//use default, no-arg constructor
superClassName newObject = this.getClass().getConstructor().newInstance();
}
Alternatively, your parent class can declare an abstract method that forces subclasses to provide a supplier:
public abstract class superClassName(){
abstract Supplier<superClassName> getInstanceSupplier();
void method(){
superClassName newObject = this.getInstanceSupplier().get();
}
}
And implement it as simply as:
public class SubClassName extends superClassName {
abstract Supplier<superClassName> getInstanceSupplier() {
return () -> new SubClassName();
}
}
Related
Is something like this possible
abstract class AbstractSuperClass {
private Entity entity;
public AbstractSuperClass(Entity entity) {
this.entity = entity;
}
public abstract void operate();
}
public class SubClass extends AbstractSuperClass {
public void operate() {
this.entity.doVoidMethod(); // is this.entity defined in instances of SubClass ?
}
}
// ... somewhere else
Entity instantiatedEntity = new Entity();
SubClass instance = new SubClass(instantiatedEntity);
instance.operate(); // does this call this.entity.doVoidMethod() inside of instance?
I want to be able to skip writing my own constructors in subclasses of an abstract class I'm writing. All of the constructors would be identical in every subclass.
If I skip writing a constructor for a subclass of an abstract class (is this even allowed?) does the abstract class' constructor get used by default?
First of all, if you don't define constructors, a default one with no argument is considered.
In other words, if you want to use new SubClass(instantiatedEntity); you must define the constructor within the SubClass that takes a single argument of type Entity.
In other words, you cannot skip writing your own constructors in case you want to pass a parameter.
Secondly, within your SubClass, you cannot call this.entity.doVoidMethod();. This because the entity attribute is private within the base class and therefore not accessible by the SubClass.
Furthermore, within AbstractSuperClass you defined public abstract Operate();. You probably meant public abstract void operate();. There's a similar mistake in the SubClass.
I want to be able to skip writing my own constructors in subclasses of an abstract class I'm writing. All of the constructors would be identical in every subclass.
You can't. Constructors are not inherited in Java:
Java Constructor Inheritance
The only quasi-exception is the default constructor. However it is strictly speaking not inheritance. If there are no constructors, the default one is added and it will call super().
If I skip writing a constructor for a subclass of an abstract class (is this even allowed?) does the abstract class' constructor get used by default?
No. Constructors of superclass are neither inherited nor copied.
According to your code above, you are using subclass is extending from an abstract class.
abstract class A{
A(){
//todo: some work
}
abstract methodA();
methodB(){
//todo:something: implementation within the abstract class.
}
}
class B extends A{
B(){
super(this);
}
}
I believe to use abstract constructor you would use the super keyword.
Some thoughts (1) you should make entity "protected" instead of "private" - that's how you make it available in the subclass, (2) it helps to use accessor methods (getter/setter) which can be inherited by subclass unlike non-defaul constructors, (3) the operate method needs a return type (I used void below), (4) the operate method needs the same signature (type sensitive name and argument types) in order to override (5) it is good practice to annotate overridden methods with #Override.
public abstract class AbstractSuperClass {
protected Entity entity;
public AbstractSuperClass() {
}
public AbstractSuperClass(Entity entity) {
this.entity = entity;
}
public setEntity(Entity entity) {
this.entity = entity;
}
public abstract void operate();
}
public class SubClass extends AbstractSuperClass {
#Override
public void operate() {
this.entity.doVoidMethod(); // protected entity is available in subclass
}
}
// ... somewhere else
Entity instantiatedEntity = new Entity();
SubClass instance = new SubClass(); // default constructor
instance.setEntity(instantiatedEntity); // inherited method
instance.operate(); // yes calls entity.doVoidMethod()
I read that you can add extra methods for an object, or override the abstract methods in this way, yet I have an error. Can you tell me if this is even possible or what I have done wrong?
public abstract class Pesti {
public abstract void ud();
}
public class EX2 {
public static void main(String[] args) {
Pesti p = new Pesti() {
public void ud() {
System.out.println("Pestele este ud!");
}
public void inn() {
System.out.println("Innoata!");
}
};
p.ud();
p.inn();
}
}
It tells me that it cannot find method inn.
What you are doing is creating an anonymous sub-class of your Pesti. However, since your p variable is of type Pesti, you can only call methods declared in the Pesti class (or any of its super-classes). Therefore you can call ud(), but not inn().
If you could cast p to the type of the sub-class, you could have called inn(), but since this is an anonymous sub-class instance, you can't cast to that type.
You could declare inn() as an abstract (or concrete) method in Pesti. Then your code would pass compilation, and the implementation of this method in the anonymous sub-class instance will be executed.
public abstract class Pesti {
public abstract void ud();
public abstract void inn();
}
You declared p as an instance of Pesti, but tried to use a method not defined in Pesti. When you declare your object as the abstract class you can only use the methods defined in this class. To use your inn() method you have to declare this method in the Pesti class as well. Alternativly you can write a class extending Pesti which implements the inn() method and declare your object as the extending class.
Pesti is an abstract class with exactly one method (which is abstract): ud(). As such, a variable declared with the type Pesti can only be used to call ud() or any method from the class Object (Pesti's implicit superclass). p is declared with this type, so despite actually being an instance of an anonymous class with the method inn(), this method is not available in the context of having a variable of declared type Pesti.
Perhaps you intended to add the inn() method to Pesti so all instances must implement it:
public abstract class Pesti {
public abstract void ud();
public abstract void inn();
}
Or perhaps you don't really want to use anonymous classes at all and want to create a subclass of Pesti with the inn() method available:
public class PestiImpl extends Pesti {
#Override
public void ud() {
System.out.println("Pestele este ud!");
}
public void inn() {
System.out.println("Innoata!");
}
}
(or you could have a layer of inheritance between the two; some abstract class extending Pesti with inn() declared as an abstract method, if you have other classes like this with the inn() method but some Pestis without).
Side note: I strongly recommend using the #Override annotation where appropriate to make your code more readable and to avoid mistakes like typos when trying to override a method. You can get most IDEs to insert it automatically.
Think you need to look at this link, I don't know what do you want to do , but you can't instantiate abstract class, you can find detailed description in my link, hope it'll help you
I came across a piece of code where there is a call to an abstract method ? I was just curious to know what it means ? Meanwhile the class is being called from a non-abstract method.
When you implement an abstract class you will also implement a concrete class. In the concrete class all abstract methods of the abstract class need to be implemented.
When a method in the abstract class call an abstract method, it refers to the implementation of this method in the concrete class.
public abstract class A {
public String method() {
// do something
int i = abstractMethod(); // abstract method call
}
public abstract int abstractMethod();
}
public class B extends A {
public int abstractMethod() { // <-- this implementation of the method is called.
return 1;
}
}
public class C extends A {
public int abstractMethod() { // <-- this implementation of the method is called.
return 100;
}
public static void main(String[] args) {
A a = new B();
a.method(); // -> abstractMethod of class B is called
a = new C();
c.method(); // -> abstractMethod of class C is called
}
}
An abstract method is a method that belongs to an abstract class but has no implementation which means that it has to be implemented (or overridden) by any children of the abstract class.
That is the whole idea of an abstract method / class: It allows the developer to define the behavior of the class later.
Assume, your class requires to "load some resource", but you want to provide different implementations for that task. Then you can override the abstract method with either loading a resource over the network or from the file system etc.
See: http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
An abstract method is a method inside an abstract class or an interface. It has no body, and one must be defined by a subclass before it can be instantiated. This allows interface classes that define some common methods, but leave some to the implementations.
The abstract methods can be called from non-abstract ones, because:
They are non-static, so they need an instance of that class to be called.
An instance of that class may not exist if the method hasn't been implemented, as the resulting class would also be abstract.
Therefore a caller will always have an instance of a class implementing that method.
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'm trying to write a factory method in an abstract class in Java (so I want it to return a new instance of the extending class, rather than the super-class).
In PHP I'd do this using the self keyword:
abstract class Superclass {
public static function factory($arg) {
return new self($arg);
}
private function __construct($arg) {}
abstract public function doSomething() {}
}
Does Java have a keyword like self I can use for this?
No; in Java, static methods are not inherited in the same way as non-static methods are. A subclass will have the static methods of its superclass, but when they execute, they will execute in context of the superclass - so there is no keyword that can be used in static methods to find out what class the method was invoked through.
Edit: A more precise formulation is that static methods are not inherited at all; however, the language allows us to use Subclass.foo() to call the static method Superclass.foo().
Based on what you seem to want to achieve, you might want to implement the Abstract Factory pattern. It goes approximately like this:
public abstract class Superclass {}
public class SubclassA extends Superclass {}
public class SubclassB extends Superclass {}
public abstract class AbstractFactory {
public abstract Superclass Create();
}
public class FactoryA extends AbstractFactory {
public Superclass Create() {
return new SubclassA();
}
}
public class FactoryB extends AbstractFactory {
public Superclass Create() {
return new SubclassB();
}
}
Now, you can e.g. create a method that takes an AbstractFactory (which, in reality, will be either a FactoryA or a FactoryB). Calling Create() on this object will produce either a SubclassA or a SubclassB.
Edit: Fixed compilation error (forgot to make the factories extend AbstractFactory).
If you absolutely have to you can use this code form a static context:
Class cls = new Object() { }.getClass().getEnclosingClass();
Object instance = cls.newInstance();
Your class need to have a nullary constructor.
You need some hacks to achieve this. One way I can think of to obtain this is:
public static <T extends SuperClass> T factory(Class<T> clazz) {
return clazz.newInstance();
}
I don't think it is possible in Java to find out the name of the "current" subclass. And especially some dynamic object generation won't be possible.
So you'll need to define that static function in every subclass instead.