Overriding method with composition - java

Consider following situation. I want to achieve the different behavior for methoddA() of class A depending upon from where it is getting call like here from class D or class C. How this can be achieved, method overriding is not working here.
class A
{
public methodA(){ //some code }
}
class B
{
A a = new A()
public methodB()
{
a.methodA();
}
}
class C
{
B b = new B();
public methodC()
{
b.methodB();
}
}
class D
{
B b = new B();
public methodD()
{
b.methodB();
}
}

What you need here is Polymorphism. First create an interface -
public interface MyInterface
{
void methodA();
}
then create two different implementations for two different behaviors -
public class First implements MyInterface
{
public void methodA() {
// first behavior
}
}
public class Second implements MyInterface
{
public void methodA() {
// second behavior
}
}
Now create your other classes as follows -
class B
{
public void methodB(MyInterface m)
{
m.methodA();
}
}
class C
{
B b = new B();
public void methodC()
{
// Pass the corresponding behavior implementation
// as argument here.
b.methodB(new First());
}
}
class D
{
B b = new B();
public void methodD()
{
// Pass the second behavior implementation.
b.methodB(new Second());
}
}
This will result in a more maintainable code.

You can pass the class name to your method as a String and in your method check
if(className.equals("A") // or use isInstanceOf() if you are passing objects of A/B
//do something
if(className.equals("B")
// do something else.
Why do you need two different implementations?
This easy trick can work for you... Please correct me if i am wrong..

I following code I have modified the method signature of Class A1 and Class B1 to accept Object and similarly while calling the methods from Class C and Class D whereever we are calling this method of class B1 pass this as reference. In Class A1 we can then check instanceof object and identify the calling class.
class A1
{
public void methodA(Object c){ //some code }
if (D.class.isInstance(c)){
System.out.println("Called from Class D");
}else if (C.class.isInstance(c)){
System.out.println("Called from Class c");
}else{
System.out.println("Called from Some diff class");
}
}
}
class B1
{
A1 a = new A1();
public void methodB(Object c)
{
a.methodA(c);
}
}
class C
{
B1 b = new B1();
public void methodC()
{
b.methodB(this);
}
}
class D
{
B1 b = new B1();
public void methodD()
{
b.methodB(this);
}
}
public class Testnew{
public static void main(String args[]){
D d = new D();
d.methodD();
C c = new C();
c.methodC();
B1 b = new B1();
b.methodB(b);
}
}

Related

How does inheritance work in this bit of code?

So guys I've been playing around with inheritance and I've stumbled upon this program :
public class HelloWorld {
static class A {
void f() { System.out.println("A"); }
}
static class B extends A {
void f() { System.out.println("B"); }
}
static class C {
void func(B b) { b.f(); }
}
static class D extends C {
void func(A a){ a.f(); }
}
public static void main(String args[]) {
( (new D())).func( (A) (new B()));
A a = new B();
a.f();
B b = new B();
C c = new D();
c.func(b);
}
}
So how come even though A and C are implemented exactly the same way in the final few lines, A's methods
get overriden by B, but C's don't get overriden by D?
The program prints as follows :
B
B
B
Because Class D function definition is more general than C. C's function takes B type parameter but D function takes type A parameter which is a parent of B. It is more general than a function defined in C.
static class D extends C {
void func(A a){
a.f();
}
}
B b = new B();
C c = new D();
c.func(b);
Variable c is pointing to D's object so c.func(b) invokes method defined in D. A is a parent of B hence B's method is called. Same as it is called using A's reference as shown below.
A a = new B();
a.f();
It is because the method func in D does not override the same of C as the signature change.
static class C {
void func(B b) { b.f(); }
}
static class D extends C {
void func(B a){ a.f(); }
}
This will result in an override of the method

How do I access Super class variables and methods in main method?

class Main
{
public static void main(String[] arg)
{
C c = new C();
c.show(); //how to access class A
}
}
class A
{
void show()
{
System.out.println("inside A");
}
}
class B extends A
{
void show()
{
System.out.println("inside B");
}
}
class C extends B
{
void show()
{
super.show(); //How to access class A
System.out.println("inside C");
}
}
Using super I can access Super Class variables and methods like C can access B's methods but what if I want to access A's methods in C. How do I do that in simple way like using super? Like two super should do the trick...
And how do I access Class A method only by allocating Class C(if name-hiding present)?
There is no construct in Java to do something like c.super.super.show() as it violates encapsulation. The Law of Demeter is a good principle illustrating why this is rightly avoided. Taking this into account, the way you can do what you request within Java is to expose a.show() in b like this:
class Main
{
public static void main(String[] arg)
{
C c = new C();
c.show(); //how to access class A
}
}
class A
{
void show()
{
System.out.println("inside A");
}
}
class B extends A
{
void show()
{
System.out.println("inside B");
}
void showA()
{
super.show();
}
}
class C extends B
{
void show()
{
super.showA(); // Calls A
System.out.println("inside C");
}
}
One way of using A's show() method in C is by creating class A object in C and using A's show function.
class C extends B
{
void show()
{
new A().show();
super.show();
System.out.println("inside C");
}
}

Why can I not call methods added to an anonymous class in Java?

If an anonymous class is extending/implementing a class/interface, why can't I add a new method?
In other words, this works:
class A {
void a() {
System.out.println("a in A");
}
}
class B extends A {
#Override
void a() {
System.out.println("a in B");
}
void b() {
System.out.println("b in B");
}
}
Why doesn't this work:
class C {
A anonA() {
return new A() {
void b() {
System.out.println("b in C");
}
};
}
}
Given:
public static void main(String[] args) {
B b = new B();
b.b();
// C c = new C();
// A anonA = c.anonA();
// anonA.b();
// yields: java: cannot find symbol \ symbol: method b()
}
Method invocations, at compile time, are determined based on the type of the expression they are invoked on. In your example, you are attempting to invoke b() on an expression of type A. A does not declare a b() method and so it won't work.
It does not work on your concrete B class example either
A notAnonA = new B();
notAnonA.b(); // fails to compile
You can very well add a new method inside the body of the new anonymous class, but you'll only be able to use it within the class or on the actual new anonymous class instance creation expression.
new A() {
void undeclared() {}
}.undeclared();

Force the execution of a method in a class

I'm using Java and I want to call the method f2 in class A from the class B. Is it possible to do this?
public class A{
private B b = new B();
public void f1(){
b.f3();
}
public void f2(){
// do something;
}
}
public class B{
public void f3(){
// Call f2 of class A from here.
}
}
You need an instance of A in class B and invoke f2 on that instance. For example, you could instantiate one inside the body of f3:
public class B {
public void f3() {
A a = new A();
a.f2();
}
}
Another way would be for f3 to receive an instance of A:
public class B {
public void f3(A a) {
a.f2();
}
}
And yet another way, you could have B instantiate one:
public class B {
private final A a;
public B() { this.a = new A(); }
public void f3() {
this.a.f2();
}
}
And lastly, B could receive one in it's constructor:
public class B {
private final A a;
public B(A a) { this.a = a; }
public void f3() {
this.a.f2();
}
}
The point being that if you want to invoke an instance method on a class you must have an instance of that class in your hand.
Finally, I notice that you have A.f1 invoking B.f3 and from there you want to invoke A.f2. So, it looks like your best option here is the second option above. That is:
public class A {
private final B = new B();
public void f1() { this.b.f3(this); }
public void f2() { /* do something */ }
}
public class B {
public void f3(A a) { a.f2(); }
}
The key here is that we are passing an instance of A to B.f3. The way that we achieve that is by passing the this reference, which is a reference to the currently executing instance. In A.f1, that would be the instance of A that is currently executing.
You need an instance of class A to do this.
public class A{
private B b = new B();
public void f1(){
b.f3(this);
}
public void f2(){
// do smthing;
}
}
public class B{
public void f3(A a){
a.f2(); // Call f2 of class A from here.
}
}
This type of code structure is usually more confusing than useful. I suggest instead doing this.
public class A{
private B b = new B();
public void f1(){
WhatAf2Needs w = b.f3();
f2(w);
}
public void f2(WhatAf2Needs w){
// do smthing;
}
}
public class B{
public WhatAf2Needs f3(A a){
return WhatAf2Needs;
}
}
If you want to call a method of the thing that called you, you have to have the caller pass itself in using the this keyword. In code, it would be:
public class A{
private B b = new B();
public void f1(){
b.f3(this);
}
public void f2(){
// do smthing;
}
}
public class B{
public void f3(A caller){
caller.f2();
}
}
You would have to instantiate class A in class B, given the way it's currently written, to make any method calls on it.
You can also declare f2 static and call it like A.f2(). This type of things depend a lot on the design of your classes though. The other answers here are very valid too.
public class A{
private B b = new B();
public void f1(){
b.f3();
}
public static void f2(){
// do smthing;
}
}
public class B{
public void f3(){
A.f2();
}
}

java constructor function newbie question

Im newbie in Java and im learning it.
Right now i have two class, i already called class B on class A constructor
class A
public A {
init();
B bb = new B(textField);
bb.doSomething();
}
void init() {
textField = new JTextField();
}
void fly() {
//can i just use bb.doFly();
}
private JTextField textField;
}
My question is, do i have to initialized B bb = new B(); on every single function i want to use on A ?
Question Edited
Its all about scope. If your attribute is at class level, then no you do not have to create a new one each time.
If the attribute is only created within a method scope, then yes you do.
The difference is
class A {
public A() {
// this is at method level scope. It is define INSIDE a method
B bb = new B();
}
}
class level scope is
class A {
// this is at class level scope. It is define OUTSIDE a method
B bb = new B();
public A() {
}
}
No, just refer to the identifier bb:
public class A {
private B bb = new B;
public A() {
}
public void foo() {
bb.printHello(); // you can only call methods on bb which class B supplies
bb.fly(); // won't work; you can only call fly() on objects of type A
}
public void bar() {
bb.printWorld();
}
public void fly() {
System.out.println("I'm flying...");
}
}
public class B {
public B() {
}
public printHello() {
System.out.println("Hello");
}
public printWorld() {
System.out.println("Hello");
}
}
Just a note: Please declare all your attributes private unless you have a good reason to not to.
class A
B bb;
public A {
bb = new B();
bb.doSomething();
}
void fly() {
bb.something()
}
}
No. Suppose you have this code this code:
public class NameOfProgram
{
public static void main(String[] args)
{
A aa = new A();
aa.fly();
}
}
Then the variable bb inside aa is created with the statement new A(). So, you don't have to create an B object and set it to bb as it already exists.
Also, you need to declare the variable outside the constructor or you will not be able to use it in other methods, like fly. To correct it you could do this:
public class A
{
B bb; <-----------------
public A()
{
bb = new B(NameOfVariableIForgotAbout);
}
public void fly()
{
bb.doFly() //Now this should work
}
}
you can also but the B bb; after the method, I just prefer it this way.
Also, your class A has a few errors (so you note for future reference). Firstly, if you want to be able to call a method from an instance of the class (A aa = new A(); aa.fly()) then you need to make the methods public like so:
public void fly()
{
//Insert code here
}
Also , you declared the constructor wrongly. Here is how you did it:
public A
{
//Insert code here
}
and it is done like this:
public A()
{
//Insert code here
}
The first error will cause a compile-time error if you make the call aa.fly() because it is neither private nor public.
The second will cause a compile-time error even if you make no call to the method.

Categories