Say I have the following class structure:
public class A{
A(int a){
...
}
}
abstract class B extends A{
}
public class C extends B{
C(int a){
super(a);
}
}
This code isn't valid in the sense that myMethod will not call A's constructor. Is there a way to do this?
What I ultimately want to do, is add functionality to a set of classes without affecting their functionality. All these classes currently extend a common class (runtimeException), so I was thinking of adding an intermediary abstract class.
(edit: the code in C shouldn't be a method, it was meant to be a constructor)
You will not be able to declare class B like you wrote. To create an instance of B you'll need to call A constructor:
public abstract class B extends A {
public B() {
super(10); //or other number
}
}
public class C extends B {
public C(int a) {
super();
}
}
In other words, you always call constructor of "previous level", whether the class is abstract or not.
In order to avoid this strange number 10 I wrote and missing int parameter of C constructor, I suggest adding to child class constructor at least all parameters parent class constructor requires for any extends pair of classes.
What I've seen commonly is a pattern like this:
public class A{
A(int a){
...
}
}
abstract class B extends A{
B(int a) {// "proxy" constructor"
super(a);
}
}
public class C extends B{
C(int a) {
super(a);
}
void myMethod(int a){
// super(a); <- note this is invalid code, you can only call this from the constructor
new C(0); // <-- this is valid
}
}
Granted, it's a bit verbose and boilerplate-y, but it allows you to avoid duplicating any functionality
Related
This is a bit weird and might ring of iffy syntax but hold with me. I've been trying for three months and I'm convinced that I need a way to do this:
public abstract class Sup{
...
//This is implemented here because I cannot create an abstract static
//only implemented by the children but called statically by methods in
//the parent (more info later on in the post):
protected static Class<? extends Sup> getTypeClass(){ return Sup.class };
public static void init(){
...
alreadyDeclaredHashMap.put(getTypeClass(), hashMapOfOtherStuff);
}
}
public class A extends Sup{
static{
init();
}
protected static void getTypeClass(){ return A.class };
}
public class B extends Sup{
static{
init();
}
protected static void getTypeClass(){ return B.class };
}
... and so on.
So that if I were to print out alreadyDeclaredHashMap, it would look like:
class A -> hashMapOfOtherStuff
class B -> hashMapOfOtherStuff
class C -> hashMapOfOtherStuff
...
But instead it prints:
class Sup -> hashMapOfOtherStuff
class Sup -> hashMapOfOtherStuff
class Sup -> hashMapOfOtherStuff
...
Because the extending classes hide getTypeClass() but can't override it. This is just an example. In reality, I am making a Units system and I have a lot of methods depending on getTypeClass() and would really love to not have to rewrite them in every extending class (of which there are an indefinite number) with the only difference in implementation being the class name.
Many thanks!
P.S. These methods do have to be static because they are being called statically (and I would rather not have to create a dummy instance or reflection just to call them).
There is no way to get that to work. The static code in class sup has no knowledge of class A and class B, even when the init method is invoked from one of them.
Static methods are not "virtual", so calling getTypeClass() from the static code in Sup will call that implementation, not any of the subclass implementation.
Now, if you want to reuse the init method from A and B, you'll have to pass as parameters.
public abstract class Sup{
...
public static void init(Class<? extends Sup> typeClass) {
...
alreadyDeclaredHashMap.put(typeClass, hashMapOfOtherStuff);
}
}
public class A extends Sup {
static {
init(A.class);
}
}
public class B extends Sup {
static {
init(B.class);
}
}
So I want to check to see if a class is assignable to a super class that contains many sub classes, something like this
public class A {
public A(){ }
}
public class B extends A {
public B(){ }
}
public class C extends B {
public C(){ }
}
public static void main() {
A a = new C();
boolean whyAmIFalse = a.getClass().isAssignableFrom(B.class);
}
Why does this return false? Obviously it can be assigned to class B as
B b = (B)a
does not return an error, so why is this returning false. Is it not the function it describes itself as? Is there a function that does accomplish what I want it to me (ie I am that class or a subclass of it)?
If what you want to do is test whether or not a's actual type is B or a subtype, you've got it backwards: it's
B.class.isAssignableFrom(a.getClass());
This is because getClass() returns the actual class, not the declared class of a variable -- a.getClass() will return the class C (C.class), which is the actual class of the object that was assigned to the variable A a and you indeed can't assign a B to a C
http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#getClass()
Because class B doesn't extend/implement class C, which is what isAssignableFrom() tests. An instance of class B might be an instance of class C, as per your example. To test that, use 'instanceof'.
public class A {
protected ClassX a;
public void foo() {
operations on a;
}
}
public class B extends A {
private ClassY b; // ClassY extends ClassX
#Override
public void foo() {
//wanna the exact same operation as A.foo(), but on b;
}
}
Sorry for such a not clear title.
My question is: in class B, when I call foo(), and I want the exact same operation as class A have on a. How do I achive that and without duplicate the same code from A?
If i leave out foo() in class B, would it work?
Or whats happening when I call super.foo() in foo();
Since ClassY extends ClassX, then you can remove private ClassY b from class B. Then you can just set your instance of ClassX to the a instance variable. This allows foo() to be inherited in class B, but still use the same logic and instance variable.
public class A {
protected ClassX a
public void foo() {
// operations on a;
}
}
public class B extends A {
// do something to set an instance of ClassY to a; for example...
public void setClassY(ClassY b){
this.a = b;
}
}
It sounds like ClassX and ClassY would have a common interface (if they have the same methods you want to call on earch, at least). Have you considered making foo() take in an object of the type of the common interface?
public class A {
private ClassX a;
protected void foo(ClassXAndClassYInheritMe anObject) {
operations on anObject;
}
public void foo() {
foo(a);
}
}
public class B {
private ClassY b;
#Override
public void foo() {
foo(b);
}
}
Don't define the foo() method in B if you want the same operation as that in A. If you want a different operation as A, override the foo() method in B. If you want to extend the foo() method in B so that it first does the operation in A and then in B, then call super.foo() at the top of the method; if you want the operation in A to come after the one in B, then call super.foo() at the end of the method foo().
You can do super.foo() inside your overrided method.
Good day,
I have the following problem:
class B extends class A and methods of both are called by another method in another class after instantiating class B (example follows):
public class A{
//fields
//constructors
//methods
}
public class B extends A{
//fields
//constructors
//methods
}
public class CALLER{
public A getA(enum E){
return Factory.getB(otherobject,E);
}
}
public class Factory{
public static B getB(object o,enum e){
//do something with enums and get B
b = new B();
//populate b
return b;
}
}
Class B does not override any method of class A.
Somehow at compile time this doesn't get any error but at runtime class CALLER excepts: java.lang.NoSuchMethodError: Factory.getB(object,enum) A
My question is: if B extends A why a method from a different class can't return A even if its return clause returns a B object directly?
In fact changing:
public static B getB(object, enum);
with
public static A getB(object, enum);
solves the exception but then I get another exception (classCast) because obviously in other parts of the code it is awaiting a B type object, not an A.
Thanks in advance.
You would get this exception if you had compiled CALLER.java with another version of Factory.java that would have getB returning A, then updated Factory.java so that getB returns B, then recompiled Factory.java but not CALLER.java
UPDATE:
Perhaps you want to do something like this:
public abstract class Factory {
public abstract A getInstance(object o, enum e);
}
public class FactoryB extends Factory {
#Override
public B getInstance(object o,enum e){
//do something with enums and get B
b = new B();
//populate b
return b;
}
}
But the factory would then need to be instanciated.
The first one looks like a reflection error. The java reflection classes look for the exact method signature "A getB(Object,Enum)" and not "B getB(Object,Enum)".
The second, as long as you actually create an object of type B in your getB(..) method, it will return this object. The classCast exception will only be thrown if you create a new A instead of a new B.
Suppose that I have interface MyInterface and 2 classes A, B which implement MyInterface.
I declared 2 objects: MyInterface a = new A() , and MyInterface b = new B().
When I try to pass to a function - function doSomething(A a){} I am getting an error.
This is my code:
public interface MyInterface {}
public class A implements MyInterface{}
public class B implements MyInterface{}
public class Tester {
public static void main(String[] args){
MyInterface a = new A();
MyInterface b = new B();
test(b);
}
public static void test(A a){
System.out.println("A");
}
public static void test(B b){
System.out.println("B");
}
}
My problem is that I am getting from some component interface which can be all sorts of classes and I need to write function for each class.
So one way is to get interface and to check which type is it. (instance of A)
I would like to know how others deal with this problem??
Thx
Can you not just have a method on the interface which each class implements? Or do you not have control of the interface?
This would provide both polymorphism and avoid the need to define any external methods. I believe this is the intention of an interface, it allows a client to treat all classes implementing it in a non type specific manner.
If you cannot add to the interface then you would be best introducing a second interface with the appropriate method. If you cannot edit either the interface or the classes then you need a method which has the interface as a parameter and then check for the concrete class. However this should be a last resort and rather subverts the use of the interface and ties the method to all the implementations.
It sounds like you are after something like this:
public static void test(MyInterface obj){
if(obj instanceof A) {
A tmp = (A)obj;
} else if(obj instanceof B) {
B tmp = (B)obj;
} else {
//handle error condition
}
}
But please note this is very bad form and indicates something has gone seriously wrong in your design. If you don't have control of the interface then, as suggested by marcj, adding a second interface might be the way to go. Note you can do this whilst preserving binary compatibility.
I'm unclear on what you're actually asking, but the problem is that you don't have a method that takes a parameter of type MyInterface. I don't know what the exact syntax is in Java, but you could do something like if (b is B) { test(b as B) } but I wouldn't. If you need it to be generic, then use the MyInterface type as the variable type, otherwise use B as the variable type. You're defeating the purpose of using the interface.
I'm not sure if I fully understand the issue, but it seems like one way might be to move the test() methods into the child classes:
public interface MyInterface {
public void test();
}
public class A implements MyInterface{
public void test() {
System.out.println("A");
}
}
public class B implements MyInterface{
public void test() {
System.out.println("B");
}
}
public class Tester {
public static void main(String[] args){
MyInterface a = new A();
MyInterface b = new B();
b.test();
}
}
You could similarly use a toString() method and print the result of that. I can't quite tell from the question, though, if your requirements make this impossible.
I think visitor design pattern will help you out here. The basic idea is to have your classes (A and B) call the appropriate method themselves instead of you trying to decide which method to call. Being a C# guy I hope my Java works:
public interface Visitable {
void accept(Tester tester)
}
public interface MyInterface implements Visitable {
}
public class A implements MyInterface{
public void accept(Tester tester){
tester.test(this);
}
}
public class B implements MyInterface{
public void accept(Tester tester){
tester.test(this);
}
}
public class Tester {
public static void main(String[] args){
MyInterface a = new A();
MyInterface b = new B();
a.accept(this);
b.accept(this);
}
public void test(A a){
System.out.println("A");
}
public void test(B b){
System.out.println("B");
}
}
Use only one public class/interface in one .java file, otherwise it'll throw error. And call the object with the object name.. You declared two methos in Teater class only, then what the purpose of declaring class A,B.
I usually use an abstract class to get around this problem, like so:
public abstract class Parent {}
public class A extends Parent {...}
public class B extends Parent {...}
That allows you to pass Parent objects to functions that take A or B.
You have 3 options:
Visitor pattern; you'll need to be able to change the MyInterface type to include a method visit(Visitor) where the Visitor class contains lots of methods for visiting each subclass.
Use if-else inside your method test(MyInterface) to check between them
Use chaining. That is, declare handlers ATester, BTester etc, all of which implement the interface ITester which has the method test(MyInterface). Then in the ATester, check that the type is equal to A before doing stuff. Then your main Tester class can have a chain of these testers and pass each MyInterface instance down the chain, until it reaches an ITester which can handle it. This is basically turning the if-else block from 2 into separate classes.
Personally I would go for 2 in most situations. Java lacks true object-orientation. Deal with it! Coming up with various ways around it usually just makes for difficult-to-follow code.
Sounds like you need either a) to leverage polymorphism by putting method on MyInterface and implementing in A and B or b) some combination of Composite and Visitor design pattern. I'd start with a) and head towards b) when things get unwieldy.
My extensive thoughts on Visitor:
http://tech.puredanger.com/2007/07/16/visitor/
public interface MyInterface {}
public class A implements MyInterface{}
public class B implements MyInterface{}
public class Tester {
public static void main(String[] args){
MyInterface a = new A();
MyInterface b = new B();
test(b); // this is wrong
}
public static void test(A a){
System.out.println("A");
}
public static void test(B b){
System.out.println("B");
}
}
You are trying to pass an object referenced by MyInterface reference variable to a method defined with an argument with its sub type like test(B b). Compiler complains here because the MyInterface reference variable can reference any object which is a sub type of MyInterface, but not necessarily an object of B.There can be runtime errors if this is allowed in Java. Take an example which will make the concept clearer for you. I have modified your code for class B and added a method.
public class B implements MyInterface {
public void onlyBCanInvokeThis() {}
}
Now just alter the test(B b) method like below :
public static void test(B b){
b.onlyBCanInvokeThis();
System.out.println("B");
}
This code will blow up at runtime if allowed by compiler:
MyInterface a = new A();
// since a is of type A. invoking onlyBCanInvokeThis()
// inside test() method on a will throw exception.
test(a);
To prevent this, compiler disallows such method invocation techniques with super class reference.
I'm not sure what are you trying to achieve but it seems like you want to achieve runtime polymorphism. To achieve that you need to declare a method in your MyInterface and implement it in each of the subclass. This way the call to the method will be resolved at run time based on the object type and not on the reference type.
public interface MyInterface {
public void test();
}
public class A implements MyInterface{
public void test() {
System.out.println("A");
}
}
public class B implements MyInterface{
public void test() {
System.out.println("B");
}
}
public class Tester {
public static void main(String[] args){
MyInterface a = new A();
MyInterface b = new B();
b.test(); // calls B's implementation of test()
}
}