Can someone explain to me how the two lines under the comment are compilable?
A a = new A();
B b = new B();
C C = new C();
// How can these work?
((G) a).methodG(a);
((B) a).methodG(a);
public class A {
A methodA() {
return this;
}
}
public class B extends A implements G {
B methodB(A a) {
return this;
}
public G methodG(A a) {
return (G) this;
}
}
public class C implements G{
C methodC(G g) {
return this;
}
public G methodG(A a) {
return (G) this;
}
}
public interface G {
G methodG(A a);
}
They won't work. You'll get a ClassCastException.
It will compile fine, since the compiler doesn't know for a fact that a is not a subclass of A that also implements G (for example B). However, during runtime, when you try to cast, it will fail.
And this is specifically one of the big reasons people shouldn't cast unless there's absolutely no choice. It breaks a lot of the type-safety you get with the compiler.
Related
My code is similar to this:
class Base{
public void handleObject(A a){
//more code...
System.out.println("A");
}
}
class Sub extends Base{
public void handleObject(B b){
//more code specific to this instance and class B
System.out.println("B");
}
public void handleObject(C c){
//more code specific to this instance and class C
System.out.println("C");
}
}
Where B and C inherit from A.
I then want to call handleObject of Base from this code:
//...
Sub s = new Sub();
A[] obj = {new B(), new B(),new C(), new A()};
for(A o:obj){
s.handleObject(o);
}
//...
And I expect Sub.handleObject(B b) to be called for each object of type B, Sub.handleObject(C c) for type C, and Base.handleObject(A a) to be called for objects of type A.
The real result is it prints "A" three times.
Is it possible to make it work using java's overloading capabilities or must I type check every object myself? If not, what is the best practice to achieve the desired behavior?
This question is very similar to mine but the answers only show why his attempts did not work and did not offer a sufficient solution for me.
I have also tried making it work using Visitor Pattern, but in their example it seems like it is required for the Base class (or at least the interface) to know about Sub, which is something I prefer not to have my project.
I suggest you use polymorphism to your advantage. Instead of trying to figure out how to behave for different classes of objects, let each class provide its own behavior:
class A {
public void handleMyself() {
System.out.println("A");
}
}
class B extends A {
#Override
public void handleMyself() {
System.out.println("B");
}
}
class C extends A {
#Override
public void handleMyself() {
System.out.println("C");
}
}
class Base {
public void handleObject(A a) {
a.handleMyself();
}
}
class Sub extends Base {
public static void main(String... args) {
Sub s = new Sub();
A[] obj = {new B(), new B(), new C(), new A()};
for (A o : obj) {
s.handleObject(o);
}
}
}
This question already has answers here:
How do I get a class instance of generic type T?
(23 answers)
Closed 6 years ago.
I want to use the polymorphism in Java in way to handle the following scenario:
public class Main {
public static void main (String[] args) {
handle(new B());
handle(new C());
}
public static void handle(A a){
// here I want to create a F<T>, in way that:
// * F must be C or D if A is B or C
// * T must B the real type of A
// e.e:
// new F<A>();
// task => see the output from D or E
}
}
class A {
}
class B extends A {
}
class C extends A {
}
class D<B> extends F{
public D(){
System.out.println("Created D of B");
}
}
class E<C> extends F{
public E(){
System.out.println("Created E of C");
}
}
abstract class F<T>{
}
The entry point is the handle method of the class Main.
The method receive an object A, that can be an instance of the class B or C.
My task is to find a way to create a new Object F that depends on the real Type of the A instance received, and the F object must be C or D depending on A, if it's B or C respectively.
Any idea will be appreciated.
Thanks.
#See Java type-erasure concepts. doc
One of the things you can do is to introduce virtual method in A:
F<? extends A> supply();
So, with the help of polymorphism you will delegate instantiation to the concrete class. This approach is similar to Template method pattern.
you can check if a is an instance of B or C using instanceof keyword, this is probably the handle method implementation your are looking for (more or less):
public static F handle(A a){
if (a instanceof B) {
// a is B, do something about that, possibly create some D<B> ?
return new D();
}
if (a instanceof C) {
// a is C, do something about that, possibly create some E<C> ?
return new E();
}
// if somehow you get here, that means something weird happened
throw new RuntimeException("unsupported case");
}
I have solved with this implementation:
public class Main {
private static D d;
public static void main (String[] args) {
handle(new B());
handle(new C());
}
public static void handle(A a){
d = solveD(a);
d.handle(a);
}
private static D solveD(A a){
if (a instanceof B){
return new E();
} else return new F();
}
}
class A {
}
class B extends A {
}
class C extends A {
}
interface D<T extends A>{
public void handle(T t);
}
class E implements D<B> {
#Override
public void handle(B b){
System.out.println("Handling E of B");
}
}
class F implements D<C>{
#Override
public void handle(C c){
System.out.println("Handling F of C");
}
}
Using Spring, it's not necessary the method solveD, because we can get the bean based on the a.getClass().getSimpleName(), annotating E and F with #Component.
I need some useful suggestion on design pattern for the following problem in Java.
I have three classes:
class A extends X implement Y {
doA()
}
class B extends X implement Y {
doB()
}
class C extends X implement Y {
doC()
}
Now I would like create a class D that should reuse methods doA, doB and doC of classes A, B and C respectively.
Can anyone suggest a design for the above problem?
I think you need to use paradigm "Prefer composition over inheritance". Design class D that includes instances of A, B, C and call their methods as necessary. In addition, D can implement Y if necessary and delegate corresponding API calls to either A or B or C.
This isn't directly possible as it stands.
Your best bet, if your design will allow, is to recreate X as an interface, and the others as interfaces that extend X. That will allow D to implement all the others.
Failing that, you might (depending on what you're trying to do) get away with having D hold a private instance of A, B and C, and then get it to delegate the methods you mention to those instances. But bear in mind that you'll have three different X instances if you do it like that.
The right answer is probably that your class hierarchy is already not quite what it should be! But there's not enough detail in the question to be certain.
You can try something like this:
class A extends X implement Y{
doA()
}
class B extends X implement Y{
doB()
}
class C extends X implement Y{
doC()
}
interface Delegator {
doSomething();
}
class DBuider {
public DBuider with(Delegator d) {
// create chain and store it
return this;
}
Chain build() {
// return new D with resulted chain
}
class Chain {
Delegator del;
Chain next;
}
}
class D implements Y {
Chain c;
static DBuilder create() {
return new DBuilder();
}
doD() {
Chain t = c;
while (t != null) {
t.del.doSomething();
t = t.next;
}
}
}
----- Usage -----
D.create().with(() -> new A().doA()).with(() -> new B().doB()).build().doD();
You could compose your new class D from your existing classes:
class D {
private A a = new A();
private B b = new B();
private C c = new C();
public void foo() {
this.a.doA();
this.b.doB();
this.c.doC();
}
}
Without knowing all the details, this feels like a composition problem.
Class D
{
private A _a = new A();
private B _b = new B();
private C _c = new C();
doA()
{
_a.doA();
}
doB()
{
_b.doB();
}
doC()
{
_c.doC();
}
}
This may or may not actually be appropriate based on what you are trying to do.
If i define
class A {
public int a;
public float b;
public A() {
a = 10;
}
}
class B extends A {
public B() {
a = 2;
}
}
class C extends A {
public C() {
b = 2.0f;
}
}
And in main
public static void main(//...) {
A a = new A();
B b = new B();
C c = new C();
a = b; //error?
b = c; //this one too?
}
I am not sure about the first error, it looks fine. You should in future post the exact error message along it. You should never ignore error messages since they tell something about the cause of the problem. The second error is obvious, it's a type mismatch: C does not extends B, so you cannot assign an instance of C to a reference which is declared as B. To fix it, you should declare it as C, A or Object (since it is the implicit superclass of all classes).
Further, your class C doesn't compile since the constructor is named A() instead of C(), but that'll probably be a copypaste error ;)
See also:
Inheritance tutorial
I recently fumbled into a problem with an API and an implementation where the following type of code appeared:
public abstract class A {
public A sum(A a) {
System.out.println("A.sum(A) called");
return null;
}
}
The implementation is a simple class:
public class B extends A {
public B sum(B b) {
System.out.println("B.sum(B) called");
return null;
}
}
When it comes to using it I write:
public class Main {
public static void main(String[] args) {
B b = new B();
A basa = new B();
b.sum(b);
basa.sum(b);
basa.sum(basa);
}
}
Which results in:
B.sum(B) called
A.sum(A) called
A.sum(A) called
I understand that B's sum does not override A's sum as its signature is different, but I'd like to provide an efficient implementation of sum for objects of effective type B. I think such design is quite classical and I would like to know how I should design my API and implementation so that it is efficient.
Of course I could provide sum(A a) in class B and check if b is an instanceof B before calling either sum(B b) or super, but I thought that instanceof was to be avoided for efficiency reasons. (if it is inefficient, it may be even less efficient with my abstract implementation)
instanceof can usually be avoided by using the visitor pattern. Depending on your needs, it may or may not be an overkill. It's flexible but quite verbose. In the example below I removed abstract from A to illustrate how it works with different types.
The trick is that when an object is asked to visit a visitor, the object itself chooses the correct accept method in the visitor. The "instanceof"-check is resolved through polymorphism. (I doubt that it's more efficient than an instanceof though.)
interface Visitor {
public A accept(A a);
public B accept(B b);
}
class A {
public A sum(A a) {
System.out.println("A.sum(A) called");
return null;
}
public A visit(Visitor sv) {
return sv.accept(this);
}
}
class B extends A {
public B sum(B b) {
System.out.println("B.sum(B) called");
return null;
}
public B visit(Visitor sv) {
return sv.accept(this);
}
}
public class Test {
public static void main(String[] args) {
A a = new A();
B b = new B();
A basa = new B();
a.visit(new SumVisitor(b)); // a.sum(b);
b.visit(new SumVisitor(b)); // b.sum(b);
basa.visit(new SumVisitor(b)); // basa.sum(b);
basa.visit(new SumVisitor(basa)); // basa.sum(basa);
}
static class SumVisitor implements Visitor {
A arg;
SumVisitor(A arg) { this.arg = arg; }
public A accept(A a) { return a.sum(arg); }
public B accept(B b) { return b.sum(arg); }
}
}
Output:
A.sum(A) called
B.sum(B) called
B.sum(B) called
B.sum(B) called
Disclamer; It was a while ago I wrote a visitor, so please correct me if I have any bugs in this (almost untested) code snippet. Or better, edit the post yourself and improve it :)
Since B instances can be summed with A instances using myA.sum(myB), you should be able to change B's definition of sum so that it does override, unless of course sum is a placeholder and isn't something that should be commutative.
UPDATE:
If this is insufficient, you could start getting fancy with generics. Here's a rough pass at what I mean:
public abstract class A {
public <T extends A> T sum(T a) {
System.out.println("A.sum(A) called");
return null;
}
public static void main(String args[]) {
B b = new B();
b.sum(b);
A basa = new B();
basa.sum(b);
basa.sum(basa);
}
public static class B extends A {
#Override
public <T extends A> T sum(T b) {
System.out.println("B.sum(B) called");
return null;
}
}
}
#aioobe is right that the generally accepted work-around is to use the Visitor pattern. I'm offering these as less complete but less verbose alternatives.
So, what makes you think instanceof is slow? It's used in several places in the JDK where they want to provide a "fast path" for certain well-known implementations of an abstract class or interface. The usual advice applies here: "Test, don't guess."