OK, so I'll start this with an example:
Let's say we have an abstract class with an interface variable, which is initialized in the constructor. The abstract class itself has a getter for that variable, it's subclasses have implementations of the interface in the constructor.
Now, the problem I'm getting is that when trying to call the getter of any of the subclasses (which is only declared in the superclass, but it should use the variable declared in their constructors) it doesn't return the implementation, it returns the interface itself.
public abstract class AbstractClass {
private final ExampleInterface exampleInterface;
public AbstractClass(ExampleInterface exampleInterface) {
this.exampleInterface = exampleInterface;
}
public ExampleInterface getExampleInterface() {
return this.exampleInterface;
}
}
public class AbstractClassSubclass extends AbstractClass {
//Instead of the interface itself, I provide my constructor it's implementation
public AbstractClassSubclass(ExampleInterfaceImplementation exampleInterfaceImpl) {
super(exampleInterfaceImpl);
}
}
public class TestClass {
private void testMethod() {
AbstractClassSubclass test = new AbstractClassSubclass(
new ExampleInterfaceImplementation()
);
//Would return ExampleInterface, instead of ExampleInterfaceImplementation
test.getExampleInterface();
}
}
Update
I believe I have fixed this using type parameters.
I'm sure I have tried it before but had a few problems...
Now it works perfectly.
Related
I am trying to extends an abstract class which is implemented one method of interface so in my subclass i am trying to implement rest of the methods declared in interface but sub class forcing me to declare all the methods of interface, please help me to fix this, thanks in advance i have added my code below. Thanks much in advance seniors.
My code
interface xxx
{
int numbers();
String names();
Double salary();
}
abstract class GetNames implements xxx
{
public String names()
{
return "Ravi";
}
}
class Check extends GetNames
//This class forcing me to implement names also
{
public int numbers()
{
return 3;
}
public double sal()
{
return 25000.00;
}
}
public class AbsUsingInterface {
}
You only need to implement methods from Interface which have not been implemented in abstract class which is a super class for your class where you are trying to implement methods.
But looks like I see one problem in your Check class.
Your interface declares this method,
Double salary();
Where as in check class you are implementing this method,
public double sal()
So this really doesn't implement a method from interface. You need to make it same as it is in interface.
Just make method in your Check class like this,
public Double salary()
{
return 25000.00;
}
While implementing/overriding a method from superclass/interface, you should always use #Override annotation so in case any of your method signature differs, it will prompt you for error right there. And yes if you declare names() method again in your subclass Check, it will override the one in abstract class.You can do something like this in your class,
abstract class GetNames implements xxx
{
#Override
public String names()
{
return "Ravi";
}
}
class Check extends GetNames
{
#Override
public int numbers()
{
return 3;
}
public double sal()
{
return 25000.00;
}
#Override
public Double salary() {
return sal();
}
#Override
public String names() { // this overrides names() method in GetNames class
return "Check";
}
}
A concrete class extending an abstract class must provide body to all the abstract method in super class.
Methods in an interface are by default- abstract unless you provide a default body.
When an abstract class implements an interface, all those methods of an interface are inherited as it is i.e. abstract
Now for your scenario, where you have provided a body for one of the inherited method of the interface, this method is no longer abstract in the scope of 'Abstract' class. So, if a class extends this abstract class, then it need not provide a body for the above method because it is no longer abstract(They can of-course override it).
You are getting an error in Check subclass that you have defined for not inheriting salary() method, not names() method that you have already defined in GetNames abstract class
your GetNames class is implementing xxx interface but you are only implementing names()
you must implement salary method.
interface xxx
{
int numbers();
String names();
Double salary();
}
abstract class GetNames implements xxx
{
public String names()
{
return "Ravi";
}
public Double salary()
{
return null;//just return null;
}
}
class Check extends GetNames
{
public int numbers()
{
return 3;
}
public double sal()
{
return 25000.00;
}
}
or just throw NotImplementedException;
I am looking for a way to have, in an abstract method, the return type to be the one of the implementation calling the method.
In other terms, I would like to write something like that:
public class GenericClass {
public <T extends GenericClass> T returnMyself() {
return (T)this; // Compiler warning, unsafe cast
}
}
public class Implem1 extends GenericClass {}
public class Implem2 extends GenericClass {}
public class Main {
public static void main(String[] args) {
Implem1 implem1 = new Implem1();
Implem1 again1 = implem1.returnMyself(); // Works fine, the type is inferred by the type of again1, I think
Implem1 again2 = implem1.<Implem1>returnMyself(); // Works fine, the type is explicitly asked by <Implem1>
Implem2 again3 = implem1.returnMyself(); // Works fine while it shouldn't.
}
}
What I am looking for is a way to declare the method so that at compilation time, returnMyself() can only return the type of the implementation invoking it (in my example, implem1 is of type Implem1), and ensure the code invoking cannot mistake/mix the types.
I searched quite a lot but couldn't find my answer anywhere (some topics seem similar but want a more general case, not explicitly the type of the implementaion invoking the method).
Some answers were correct, but always implied to override the method in each Implementation class, which may be cumbersome and bug-prone on my side. I'm ideally looking for a method that i would have to write only once in the Abstract class.
Any help/answer appreciated :D
You can do it like this:
public class Parent {
public Parent returnMyself() {
return this;
}
}
public class Child extends Parent {
public Child returnMyself() {
return this;
}
}
This is no problem because if you store a Child instance in a Parent variable then you expect a Parent return type of returnMyself(). Even if it is actually a Child object, the Child returned by returnMyself() extends Parent so there you go.
Since you mention abstract in your problem description, how about follow a model similar to Java's Enum class, where the generic type is in the class definition?
public abstract class GenericClass<T extends GenericClass> {
public abstract T returnMyself();
}
public class Implem1 extends GenericClass<Implem1> {
#Override
public Implem1 returnMyself() {
return this;
}
}
public class Implem2 extends GenericClass<Implem2> {
#Override
public Implem2 returnMyself() {
return this;
}
}
public class Main {
public static void main(String[] args) {
Implem1 implem1 = new Implem1();
Implem1 again1 = implem1.returnMyself(); // Works fine
Implem1 again2 = implem1.returnMyself(); // Works fine
Implem2 again3 = implem1.returnMyself(); // Does not compile
}
}
Since you want to write these methods inside of subclasses, this appears to be possible. You can override a method and have a different return type as long as the new return type is an extension of the old one:
Can overridden methods differ in return type?
I have a Spring managed class that extends a base service. I'd like to write the base service in a way that any implementation classes must provide a specific FileAnalyzer instance. But I don't want to make the FileAnalyzer class to be spring managed.
It that possible? Because a super() class always has to be the first call in a constructor, so I cannot instantiate any classes before invoking the base constructor.
Example:
public abstract class BaseService {
BaseService(FileAnalyzer analyzer, String path) {
this.path = path;
//perform any action with analyzer.
}
}
#Service
public class TextfileService {
public TextfileService() {
//ERROR: super() must be first call in constructor
FileAnalyzer analyzer = new FileAnalyzer();
analyzer.configure(..);
super(analyzer, "c:\logs");
}
}
It that possible? Because a super() class always has to be the first call in a constructor
Yes it's possible. Just move the code in a private static method and call it from inside the super() call.
#Service
public class TextfileService {
public TextfileService() {
super(getFileAnalyzer(), "c:\logs");
}
}
private static FileAnalyzer getFileAnalyzer(){
FileAnalyzer analyzer = new FileAnalyzer();
analyzer.configure(..);
return analyzer;
}
Alternative way:
If FileAnalyzer is your custom class written by you then just make a change in the return type of the method configure() as shown below:
#Service
public class TextfileService {
public TextfileService() {
super(new FileAnalyzer().configure(...), "c:\logs");
}
}
FileAnalyzer.java
public FileAnalyzer configure(){
...
return this;
}
You can use a lookup method injection.
Just assign a lookup method and it will be called whenever you instantiate a new object of this class.
Check this answer.
I thought I understood how to use .class and Class<> but I guess not. The below super(ApprovalWorkstation.class is not being mapped to the constructor. How can I be sure that I'm passing a class reference so that the base WorkstationRequest can instantiate it?
public class ApprovalWorkstation extends Workstation {
public ApprovalWorkstation(WorkstationEntity entity) {
super(entity);
}
}
public class WorkstationRequest extends com.production.socket.request.WorkstationRequest {
public WorkstationRequest() {
super(ApprovalWorkstation.class); //unable to map to constructor
}
}
This is the base WorkstationRequest that's extended above
public class WorkstationRequest {
private Class<Workstation> workstationClass;
public void WorkstationRequest(Class<Workstation> workstationClass) {
this.workstationClass = workstationClass;
}
update
I'm sorry for the confusion, my constructor actually has Class<Workstation> and not Workstation as I initially had.
In order to be able to pass both Workstation class and it's child classes you should change definition of WorkstationRequest to the following:
public class WorkstationRequest {
private Class<? extends Workstation> workstationClass;
public WorkstationRequest(Class<? extends Workstation> workstationClass) {
this.workstationClass = workstationClass;
}
}
Correct me if I am wrong, but you are passing in a Workstation instance while what needed is a Class<Workstation>. Maybe use workstationClass.getClass() instead?
You're trying to assign an instance of Worstation to field of type Class<Workstation> which is obviously not the same.
What you're probably trying to do is:
public WorkstationRequest(Class<Workstation> workstationClass) {
Of course there is no return type (void) in constructors. Your "constructor" is simply a method:
public void WorkstationRequest(Class<Workstation> workstationClass) { // method
public WorkstationRequest(Class<Workstation> workstationClass) { // constructor
There is no constructor that takes a Class as a parameter in the base WorkstationRequest class.
Constructors do NOT have a return type, so public void WorkstationRequest needs to be changed to public WorkstationRequest.
I have an abstract class that should implement a public field, this field is an interface or another abstract classe.
something like this:
public abstract class GenericContainer {
public GenericChild child;
}
public abstract class GenericChild {
public int prop1=1;
}
public abstract class SpecialChild extends GenericChild {
public int prop1=2;
}
Now i have another specialized class Container:
public abstract class SpecialContainer extends GenericContainer {
public SpecialChild child=new SpecialChild(); //PAY ATTENTION HERE!
}
Java allow me to compile this, and i IMAGINE that the field child in SpecialContainer is automatically overloading the field child of the GenericContainer...
The questions are:
Am i right on this? The automatic 'overloading' of child will happen?
And, more important question, if i have another class like this:
public class ExternalClass {
public GenericContainer container=new SpecialContainer();
public int test() {
return container.child.prop1
}
}
test() will return 1 or 2? i mean the GenericContainer container field what prop1 will call, the generic or the special?
And what if the special prop1 was declared as String (yes java allow me to compile also in this case)?
Thanks!
In Java, data members/attributes are not polymorphic. Overloading means that a field will have a different value depending from which class it's accessed. The field in the subclass will hide the field in the super-class, but both exists. The fields are invoked based on reference types, while methods are used of actual object. You can try it yourself.
It's called, variable hiding/shadowing, for more details look on here
It isn't overriding anything, you're just hiding the original field at the current class scope. If you use a variable with the subtype you will still be able to access the original property. Example:
abstract class GenericContainer {
public GenericChild child;
}
abstract class GenericChild {
public int prop1=1 ;
}
class SpecialChild extends GenericChild {
public int prop1=2;
}
class SpecialContainer extends GenericContainer {
public SpecialChild child;
}
public class Main {
public static void main( String ... args ) {
GenericContainer container = new SpecialContainer();
container.child = new SpecialChild();
System.out.println( container.child.prop1 );
SpecialChild child = (SpecialChild) container.child;
System.out.println( child.prop1 );
}
}
This prints 1 and then 2.
From SpecialChild you would also be able to go up one level using super:
class SpecialChild extends GenericChild {
public int prop1=2;
public int getOriginalProp1() {
return super.prop1;
}
}
Regarding
....and i IMAGINE that the field "child" in SpecialContainer is automatically overloading the field 'child' of the GenericContainer...
No. Fields don't get overridden, only methods do.
This is one reason why use of (overridable) getter and setter methods are preferred to direct access to fields. Your fields should almost all be private.
As for your design, there's no need for your SpecialContainer class to have a SpecialChild field, but instead the SpecialChild object should be placed in the GenericChild field.
Why nobody is observing that program will throw NullPointerException.
subclass's field with same name will hide super class's field. There is no overriding with field. Overriding is only possible with methods.
Original Code by Author:
public abstract class GenericContainer {
public GenericChild child;
}
public abstract class GenericChild {
public int prop1=1;
}
public abstract class SpecialChild extend GenericChild {
public int prop1=2;
}
public abstract class SpecialContainer extends GenericContainer {
public SpecialChild child=new SpecialChild(); //PAY ATTENTION HERE!
}
public class ExternalClass {
public GenericContainer container=new SpecialContainer();
public int test() {
return container.child.prop1
}
}
Java allow me to compile this, and i IMAGINE that the field "child" in
SpecialContainer is automatically overloading the field 'child' of the
GenericContainer...
Firstly, Inheritence doesn't apply to variables. Fields(Insatnce variables) are not overridden in your sub-class.they are only visible in your subclass if they are marked with either public, protected or default.
To answer your question it maintains both instances. And depending on how you refer to the container (either through the abstract or the impl) determines which variable you are referring to.
public class Test {
public abstract class Container{
public Generic gen = new Generic();
}
public class ContainerImpl extends Container{
public GenericImpl gen = new GenericImpl();
}
public class Generic{
public int prop = 0;
}
public class GenericImpl extends Generic{
public int prop = 1;
}
public Test(){
Container c = new ContainerImpl();
System.out.println(c.gen.prop); // Outputs "0"
System.out.println(((ContainerImpl)c).gen.prop); // Output "1"
}
public static void main(String[] args) {
new Test();
}
}
The bigger question at hand is, why would you design something like this? I'm assuming you are asking from a theoretical perspective.
My 2 cents, this isn't great OO design. You would be better off making the public variables private and assigning their values through a constructor or property setter. As-is, it will lead to unexpected results in your code.