I have the following classes in C++
ParentClass
{
virtual int MyMethod();
}
class ExistingOne : ParentClass {...}
class ExistingTwo : ParentClass {...}
Now I would like to create a class that can extend either of the Existing classes and override a couple of their methods plus call a method in the Existing class under some conditions.
In C++ this is done using the following:
template< class BaseTemplate >
class MyClass : public BaseTemplate
{
int MyMethod()
{
DoSomething();
return BaseTemplate::MyMethod();
}
}
How is this done in Java?
So far I have
public abstract class ParentClass
{
public abstract int MyMethod();
}
public class ExistingOne extends ParentClass {...}
public class ExistingTwo extends ParentClass {...}
public class MyClass<T extends ParentClass>
{
public int MyMethod()
{
DoSomething();
return T.MyMethod(); //MyMethod must be statically defined?
}
}
Oh and lastly, I cannot modify the "Existing" or Parent class.
So is this the correct approach? How do I solve the static requirement?
In the C++ class definition, MyClass extends BaseTemplate. In the Java example, MyClass doesn't extend ParentClass, thus getting the expected problem.
In Java, just change the definition to:
public class MyClass<T extends ParentClass> extends ParentClass {
#Override
public int MyMethod() {
DoSomething();
return super.MyMethod();
}
}
Since MyMethod is abstract in ParentClass, this gives a compiler error. Instead, you would need to call MyMethod from an instance of ParentClass. This can be fixed by having a field T t inside MyClass:
public class MyClass<T extends ParentClass> extends ParentClass {
T t;
public MyClass(T t) {
this.t = t;
}
#Override
public int MyMethod() {
DoSomething();
return t.MyMethod();
}
}
Otherwise, using generics and extending ParentClass here won't have any sense at all.
Related
Is there a way to extend an abstract class with generic enum types? When I extend it and implement myMethod below, only the method from the abstract class gets called.
first i define abstract class with method myMethod where i would like to make decisions based on the enum value.
public abstract class MyAbstractClass <T extends enum<T>> {
public void myMethod(T cmd) {
//i want to override this
}
public void update(T cmd) {
myMethod(cmd);
}
}
define an enum and extend the class, but the child class myMethod never gets called(only the myMethod of abstract class gets called).
enum CMD {
CMD_1, CMD_2
}
public class Child extends MyAbstractClass<CMD> {
...
public void myMethod(CMD cmd) {
if (cmd == CMD_1) { //do something }
}
...
}
instantiate and call
Child child = new Child();
child.update(CMD.CMD_1);
Yes. Use T extends Enum<T>:
public abstract class MyAbstractClass <T extends Enum<T>> {
public void myMethod(T cmd) {}
}
See live demo of your code, with this change, compiling OK.
If you want to select the behaviour according to the enum value, then one way to do it is to put the behaviour into each enum value, e.g.:
enum Command {
CMD1 {
#Override
void execute() {
System.out.println("Command.CMD1");
}
},
CMD2 {
#Override
void execute() {
System.out.println("Command.CMD2");
}
};
abstract void execute();
}
public static void main(String[] args) {
final Command cmd = Command.CMD1;
cmd.execute();
}
Let's say I have an abstract class, an extending class, and an interface like this:
public abstract class SuperClass {
...
public void foo() {...}
...
}
public class SubClass extends SuperClass implements MyInterface {...}
public interface MyInterface {
public void bar();
}
Note that I have a few subclasses of SuperClass implementing MyInterface, but not all of them.
Also let's say, I have another class with a constructor like this:
public class AnotherClass {
private SuperClass sc;
public AnotherClass(SuperClass superclass) {
sc = superclass;
}
...
}
My question now is, how would I be able to ensure that the given object in the constructor also implements MyInterface? I would need the object sc to be able to run both methods foo() and bar(). How can I accomplish this?
You could introduce another class to the hierachy:
public class NonImplementingSubClass extends SuperClass {...}
public class ImplementingSubClass extends SuperClass implements MyInterface {...}
All your subclasses that should implement your interface, will then extend ImplementingSubClass
public class SubClass extends ImplementingSubClass {...}
public class AnotherClass {
private ImplementingSubClass sc;
public AnotherClass(ImplementingSubClass superclass) {
sc = superclass;
}
...
}
You can use generics with intersection types,
public class AnotherClass<T extends SuperClass & MyInterface> {
private T sc;
public AnotherClass(T superclass) {
sc = superclass;
}
void fn(){
// use both methods
sc.foo();
sc.bar();
}
...
}
Now, AnotherClass will only allow types that are SuperClass and implement MyInterface.
public abstract class SuperClass implements MyInterface {
...
public void foo() {...}
...
}
public class SubClass extends SuperClass{}
public interface MyInterface {
public void bar();
}
I have created some interface such that:
public interface A{
}
and i would like to call the method a that I have already implemented in class B in interface A such that:
public class B{
public boolean a(){
return true;
}
}
public interface A{
public void call {
a();
}
}
without any errors, any help please?
What you want to do is strictly speaking impossible, as you cannot define method implementations in an interface. You can get something similar by defining an implementation of the interface that extends B. Hopefully that is close enough.
public class AImplementation extends B implements A{
public void call(){
a();
}
}
If you are using any java version before 8, then stick with the answers of #tinker and #Davis Broda. They provide better design since they do not couple your interface to the B class. If you insist however, in java 8 you can have default method implementations as well as static methods in an interface.
If your method is for inheritance then you have to use a default method. Add the default keyword:
default void call() {
...
}
Now the problem is how to get a reference to the class in order to call the method since you cannot have instance fields in interfaces. You have two choices:
Pass the object of B as a method parameter:
public interface A{
default void call(B b) {
b.a();
}
}
or make the method in B static
public interface A{
default void call() {
B.a();
}
}
If your method is not for inheritance but just a utility than you can make it static as :
public interface A{
public static void call() {
B.a();
}
}
I agree with #Davis Broda's answer, there is no way to have a method definition in an interface. But I have another way to address this.
You can have the interface and then have an abstract class implement this interface, and then have all other classes extend the abstract class. The abstract class doesn't have to extend the class from where you want to call the method, you could call it from an instance of that class too.
public interface A {
void caller();
}
public class B {
public void callMe() {
}
}
public class AbstractA implements A {
private B b;
public AbstractA(B b) {
this.b = b;
}
#Override
public void caller() {
b.callMe();
}
}
This way, all implementations of AbstractA will be able to call B's callMe method. And you can access this directly from the interface using this code:
A anInstance = someInstance;
anInstance.caller();
Your question is not very clear, but if I'm guessing right, you want interface A to be kind of a generic caller.
If you're using Java 8, you can achive that using a method reference:
public class B {
public boolean a() {
return true;
}
}
public interface A<T> {
default T call(Supplier<T> s) {
return s.get();
}
}
public class AImpl
implements A<Boolean> {
}
public class Sample {
public static void main(String[] args) {
AImpl a = new AImpl();
B b = new B();
boolean result = a.call(b::a);
System.out.println(result); // true
}
}
This uses Supplier<T> because your method a() in class B returns a boolean and does not receive any arguments.
I have an abstract class A, and an abstract class B inheriting A.
Then, I have a class C(not abstract) that inherits B.
I need to override some methods declared abstract in A, and not implemented in B to be implemented in C.
But when I try to do this, and add an Override annotation on top of my method, it says its not valid as that method does not exist in the parent.
How can I do this?
Code with signatures:
public abstract class A {
abstract protected EntityType getEntityType();
abstract protected ActionResponse doProcessing();
}
public abstract class B extends A {
#Override
EntityType getEntityType() {
....
...
}
}
public class C extends B {
#Override
ActionResponse doProcessing() {
...
..
}
}
Access Modifier of the Sub class can't weaker than it's Super Class. It is better to change the Access Modifier of the sub classes to protected from default
A:
public abstract class A {
public abstract D getClassD();
}
B:
public abstract class B extends A{
}
D:
public class D {
}
And C:
public class C extends B {
D d = new D();
#Override
public D getClassD() {
return this.d;
}
}
It's correct. You cannot create class C without override method getClassD().
Please add field and initialize it.
If you use Eclipse you can change in setting that IDE should put #Override or not
Your scenario works just fine in JavaSE 1.7. What version of java are you using?
public abstract class A {
protected abstract Integer getMyInt();
protected abstract String getMyString();
}
public abstract class B extends A {
#Override
protected String getMyString(){
return "The answer is";
}
}
public class C extends B {
#Override
protected Integer getMyInt() {
return 42;
}
}
public class Test {
public static void main(String[] args) {
C c = new C();
System.out.println(c.getMyString() + " " + c.getMyInt());
}
}
If you could access the grandparent directly you would create a dependency on the implementation of the father, and this would violate encapsulation.
So suppose I have 2 classes:
public class A
{
public void
f()
{
}
}
public class B
{
public void
f()
{
}
}
I would like to write a generic static method that could call f when passed an instance of A or B. I tried:
public class C
{
public static <T extends A & B> void
g(T t)
{
t.f();
}
public static void main(String[] args)
{
A a = new A();
g(a);
}
}
But the compiler claims A is not a valid substitute for "T extends A & B", which I assume is because T must extend BOTH A and B, which obviously A does not. I could not find a way to specify something like "T extends A OR B". Is something like this not achievable? I am a java neophyte, so any help with this would be appreciated.
You can only specify one generic type. Use interfaces instead.
An interface specifies a certain set of methods, each member of it has to have. A class can implement multiple interfaces.
In your example, I would define an interface with the method f():
public interface MyInterface {
void f();
}
Let A and B implement the interface:
public class A implements MyInterface
{
#Override
public void f() {
// ...
}
}
public class B implements MyInterface
{
#Override
public void f() {
// ...
}
}
Then you can just specify the interface as type of the argument for your method:
public static void g(MyInterface obj)
{
obj.f();
}
For more detail on interfaces, check the Java documentation: What Is an Interface?