Implement a common function accepting argument of two different classes? - java

I have two classes A and B and they both have a common field in them, and I want to create a function in which if I pass Class A object then I want to set that common field value to the passed value and if I pass Class B object then I want to set that common field value to the passed value. Can anyone please tell me how can I do this, I am new to Java Generic Classes.
Otherwise I would have to make two different functions OR I would have to make an if and else which would decide that passed object belongs to which class ??
Class A
public class A{
int footer;
public void setFooter(int fo) {
footer = fo;
}
}
Class B
public class B{
int footer;
public void setFooter(int fo) {
footer = fo;
}
}
Class D
public class D{
public void change_footer(T generic_param, int value) {
generic_param.setFooter(value);
}
}
Class HelloWorld
public class HelloWorld{
public static void main(String []args){
Here I want to call
A a = new A();
new D().change_footer(a, 5);
B b = new B();
new D().change_footer(b, 5)
}
}
Thank You

And if I got all of the question wrong, and nor A nor B are generic, AND the type of field is fixed.
then you mean something like:
class D {
/*public <T extends Super> would be muuuch nicer here as well!*/
public /*static*/ <T> void change_footer(T obj, int data) {
//otherwise, you could just cast to Super...and set dat field.
if (obj instanceof A) {
((A) obj).setField(data);
} else if (obj instanceof B) {
((B) obj).setField(data);
} // else ... ?
}
}
Original answer:
Easy peasy (the "straight forward" implementation produces the desired results.):
class A<T> {
T daField;
public void setField(T pField) {
daField = pField;
}
public T getField() {
return daField;
}
}
class B<T> extends A {//empty
}
class Test {
public static void main(String... args) {
B<Object> testB1 = new B<>(); //
testB1.setField(new Object());
System.out.println(testB1.getField());
B<String> testB2 = new B<>();
testB2.setField("blah blah");
System.out.println(testB2.getField());
B<Integer> testB3 = new B<>();
testB3.setField(42);
System.out.println(testB3.getField());
}
}
System.out:
java.lang.Object#6d06d69c
blah blah
42
It get's (little) more complicated, when you want to instantiate Ts ...but still possible/other question. :)
Edit to your comment:
If there's only one common field, then why not:
/*abstract */class Super<T> {
T daField;
public void setField(T pField) {
daField = pField;
}
public T getField() {
return daField;
}
}
? ...and:
class A<T> extends Super { ... }
class B<T> extends Super { ... }

Related

Is it possible to store code in an object that can be run from another object?

In Java,
class BlaBlaThirty extends Parent {
void foo(String s, int i) {}
}
class BlaBlaTwentyNine extends Parent {
void foo(int i, Bla a, This t, Other o) {}
}
class BlaBlaFive extends Parent {
void foo(Bla a, Other o) {}
}
...
Many different classes all with a method foo().
ArrayList<Object> arr;
arr.add(blablai);
arr.add(blablaj);
arr.add(blablak);
...
array arr contains many objects which are instances of these classes.
The problem is that all these foo() methods do not have the same parameters. How to call these methods with the right parameters?
arr.get(i).foo(?,?,?);
my solution:
all foo method have one ArrayList params parameter which contains all the needed parameters as Object :
class BlaBlaX {
void foo(ArrayList<Object> params) {}
}
then, I add the variables names of the variables needed in foo() in the class containing foo. before calling foo(), I call getFooParams() :
class BlaBlaTwentyTwo extends Parent {
ArrayList<Object> getFooParams() {
ArrayList<String> p;
p.add("i");
p.add("banana");
p.add("volkswagen");
return p;
}
void foo(ArrayList<Object> params) {
Int i = (int) params.get(0);
Fruit banana = (Fruit) params.get(1);
Car volkswagen = (Car) params.get(2);
}
}
object calling foo() methods contains all the variables required in foo() :
class ObjCallingFoo {
int i;
Fruit banana;
car volkswagen;
//see below for what is here to call foo()
}
import java.lang.reflect.Method;
import java.lang.reflect.Field;
p = arr.get(i).getFooParams();
int size = p.size();
ArrayList<Object> arrParams = new ArrayList<>();
for (int i = 0; i < size; i++) {
String variableName = p.get(i);
Field field = objCallingFoo.getClass.getField(variableName);
arrParams.add(field);
}
I can now call foo with the right parameters :
arr.get(i).foo(arrParams);
I haven't tested yet.
What do you think of that?
Is it possible to store code in an object that can be run from another object?
OR
How to call a method with parameters of another object if we don't know what are the specific member variables to pass as parameters to the method in calling object?
You need an abstraction that includes the specific method to call and how to call it. This is what the Strategy and Command design patterns can do.
In general, you can use instanceof:
Object parent = obj.get(i);
if(parent instanceof BlaBlaThirty)
((BlaBlaThirty)parent).foo(?,?);
else if(parent instanceof BlaBlaTwentyNine)
((BlaBlaTwentyNine)parent).foo(?,?,?);
else if(parent instanceof BlaBlaFive )
((BlaBlaFive )parent).foo(?,?);
P.S. This is not good to hold all these objects in one list. Your code organization should be refactored indeed!
You could have different constructors and a basic method foo() in Parent.
Then you can override it in every class und do something different with the fields.
But i think it is an option but maybe you should refactor your code/abstraction/inheritance in another way.
class Parent {
void foo(){}
}
class BlaBlaThirty extends Parent {
//Contructor with String s, int i
void foo() {
//Do something here with fields String s, int i
}
class BlaBlaTwentyNine extends Parent {
//Contructor with int i, Bla a, This t, Other o
void foo() {
//Do something here with fields int i, Bla a, This t, Other o
}
class BlaBlaFive extends Parent {
//Constructor Bla a, Other o
void foo() {
//Do something here with fields Bla a, Other o
}
...
Many different classes all with a method foo().
ArrayList<Parent> parent;
parent.add(blablai);
parent.add(blablaj);
parent.add(blablak);
...
parent.foo()
parent.foo()
parent.foo()
You may want to use a interface:
public interface Blainterface{
public void foo();
}
public class BlaBlaTwentyNine extends Parent implements Blainterface {
public void foo() {}
}
....
ArrayList<Blainterface> obj;
obj.add(blablai);
obj.add(blablaj);
obj.add(blablak);
//now you can acces it like
obj.get(2).foo();
It gets even better. You may have a class that doesn't implement the interface but with a method that looks the same:
public interface Blainterface{
public void foo();
}
public class Blubclass{
public void bar(){ //note its bar here and not foo()!!!
//do something cool!
}
}
//...
ArrayList<Blainterface> obj;
obj.add(blablai);
obj.add(blablaj);
obj.add(blablak);
Blubclass blub = new Blubclass(); //note that blub has no foo() method.
obj.add(blub::bar);
//And that call will work too:
obj.get(3).foo(); //this will call bar() in the Blubclass.
now one step further with someting that has different parameters:
public interface Blainterface{
public void foo();
}
public class Bazclass{
public void baz(Sting name){ //note its baz here and not foo() and it has a parameter!!!
//do something cool!
}
}
//...
ArrayList<Blainterface> obj;
obj.add(blablai);
obj.add(blablaj);
obj.add(blablak);
Bazclass baz = new Bazclass(); //note that baz has no foo() method and a parameter.
obj.add(()->baz.baz("name"));//mapping of parameters
//And that call will work too:
obj.get(3).foo(); //this will call baz("name") in the Bazclass. Even though we use a different method name and parameters for the call.
Only thing you need is to define the signature you want to use, when you call the methods, in an interface.
And you have to tell java how to map the parameters(it cant't guess).
Finally what I may do,
class FooParamsNeeded {
public boolean blaBlaI;
public boolean blaBlaJ;
public boolean i;
public boolean blaBlaK;
public boolean banana;
public boolean blaBlaL;
public boolean volkswagen;
public boolean blaBlaM;
...
}
//------------ in object where foo() is, there is a specic getFooParams() method with parameters needed set to true----------
FooParamsNeeded getFooParams() {
FooParamsNeeded fpn = new FooParamsNeeded();
fpn.i = true;
fpn.banana = true;
fpn.volkswagen = true;
return fpn;
}
//--------------------
class FooParams {
public BlaBlaI blaBlaI;
public BlaBlaJ blaBlaJ;
public int i;
public BlaBlaK blaBlaK;
public Fruit banana;
public BlaBlaL blaBlaL;
public Car volkswagen;
public BlaBlaM blaBlaM;
...
}
//-------in object where other object's foo() method is called-----
FooParams setFooParams(FooParamsNeeded fpn) {
FooParams fp = new FooParams();
if (fpn.blaBlaI)
fp.blaBlaI = blaBlaI;
if (fpn.blaBlaJ)
fp.blaBlaJ = blaBlaJ;
if (fpn.i)
fp.i = i;
if (fpn.blaBlaK)
fp.blaBlaK = blaBlaK;
if (fpn.banana)
fp.banana = banana;
if (fpn.blaBlaL)
fp.blaBlaL = blaBlaL;
if (fpn.volkswagen)
fp.volkswagen = volkswagen;
if (fpn.blaBlaM)
fp.blaBlaM = blaBlaM;
...
return fp;
}
FooParamsNeeded fpn = arr.get(i).getFooParams();
FooParams fp = setFooParams(fpn);
arr.get(i).foo(fp);
//-------------------------------------
I think I should have 10-15 possible different paramaters and so 10-15 if statements in setFooParams().

Java - How to call method class with interface without know class name

I'm new in java, I want to call method class from implemented Class with interface without know class name "ClassA", which only know Object c and I have 2 file.
File (1) CobaInterface.java
package cobainterface;
public class CobaInterface {
public static void main(String[] args) {
ImplementedClass implementedClass = new ImplementedClass();
ClassA clsA = new ClassA();
implementedClass.myMethodFromClassA(clsA);
}
}
class ClassA{
public Integer getTwo(){
return 2;
}
}
interface MyInterface {
public void myMethod();
//here interface
public void myMethodFromClassA(Object c);
}
File (2) : ImpementedClass.java
package cobainterface;
public class ImplementedClass extends CobaInterface {
public void myMethodFromClassA(Object c) {
//System.out.println(c.getTwo()); <- wrong when call method c.getTwo()
}
}
How about if I want to call method getTwo() from ClassA without know Class Name, which only know Object c from file (2) as describe in code above. Thanks for advance.
You should use generic types so the implementation knows what the object will be,
interface MyInterface<T> {
public void myMethod();
//here interface
public void myMethodFromClassA(T c);
}
The impl becomes,
package cobainterface;
public class ImplementedClass Implements MyInterface<ClassA> {
public void myMethodFromClassA(ClassA c) {
//System.out.println(c.getTwo()); <- wrong when call method c.getTwo()
}
}
All together,
class Scratch {
public static void main(String[] args) {
ImplementedClass implementedClass = new ImplementedClass();
ClassA clsA = new ClassA();
implementedClass.myMethodFromClassA(clsA);
}
}
class ImplementedClass implements MyInterface<ClassA> {
#Override
public void myMethod() {
}
#Override
public void myMethodFromClassA(ClassA c) {
System.out.println(c.getTwo());
}
}
class ClassA {
public Integer getTwo() {
return 2;
}
}
interface MyInterface<T> {
void myMethod();
void myMethodFromClassA(T c);
}
You could also do a cast
System.out.println((MyClass)c.getTwo());
but you will lose all benefit of type saftey.

Java: builder pattern, inheritance and generics

I want to implement Builder Pattern with inheritance. So I have 4 following classes: one abstract class (ClassA), ClassB, ClassC. TestTest class is used to see how all this works:
public abstract class ClassA {
private String aString;
public String getaString() {
return aString;
}
public abstract class ClassABuilder<T extends ClassABuilder>{
public T setaString(String str) {
ClassA.this.aString = str;
return (T)this;
}
public abstract ClassA build();
}
}
public class ClassB extends ClassA{
private String bString;
public String getbString() {
return bString;
}
public class ClassBBuilder<T extends ClassBBuilder> extends ClassA.ClassABuilder<T>{
public T setbString(String str) {
ClassB.this.bString = str;
return (T)this;
}
#Override
public ClassB build(){
return ClassB.this;
}
}
}
public class ClassC extends ClassB{
private String cString;
public String getcString() {
return cString;
}
public static ClassCBuilder<ClassCBuilder> newBuilder(){
return new ClassC().new ClassCBuilder();
}
public class ClassCBuilder<T extends ClassCBuilder> extends ClassB.ClassBBuilder<T>{
public T setcString(String str) {
ClassC.this.cString = str;
return (T)this;
}
#Override
public ClassC build(){
return ClassC.this;
}
}
}
public class TestTest {
public static void main(String[] args) {
// TODO code application logic here
ClassC C=ClassC.newBuilder()
.setaString(null)
.setbString(null)
.setcString(null) //LINE XXX
.build();
}
}
The problem is that at TestTest at LINE XXX I get can't find symbol "setcString". What do I do wrong?
Let's track it down along the hierarchy:
First consider this signature:
class ClassABuilder<T extends ClassABuilder>
When you call setaString(null) the returned T will be an object that extends ClassABuilder. The compiler knows that this is a ClassBBuilder and thus will allow you to call setbString(null).
However, since the definition states T is required to extend a raw ClassBBuilder only any information on ClassBBuilder's generic types will be lost. Thus the compiler only knows that T is a ClassBBuilder but not that it's actually a ClassCBuilder which extends ClassBBuilder<ClassCBuilder> and hence doesn't know about setcString() on the returned type.
As has already been mentioned, using T extends ClassABuilder<T> will fix that since now the compiler knows there's another generic type to be passed down the hierarchy.
newBuilder() would then have to look like this:
public static ClassCBuilder<?> newBuilder(){
//you have too create a raw type here so you'll have to ignore/suppress/live with the warning
return (new ClassC().new ClassCBuilder());
}
As #AndyTurner already observed, the problem is that you use raw versions of your builder class types as type parameters. He did not go into detail, but the upshot is this:
ClassC C=ClassC.newBuilder() // yields a ClassCBuilder<ClassCBuilder>
.setaString(null) // yields a raw ClassCBuilder (type parameter)
.setbString(null) // yields a raw ClassBBuilder (type parameter bound)
.setcString(null) // ERROR: no such method on ClassBBuilder
.build();
To fix this with minimal change to your class structure and strategy, you must not only correct the type parameter bounds for your builder classes, as Andy advised ...
ClassABuilder<T extends ClassABuilder<T>>
... etc., but also make a change to ClassC.newBuilder(), such as to make it generic:
public static <T extends ClassCBuilder<T>> ClassCBuilder<T> newBuilder() {
return new ClassC().new ClassCBuilder<T>();
}
With that combination of changes, your code compiles for me.
I would like to post here the test demonstrating builder pattern with deep inheritance.
class TypeParamTest {
#Test
void test() {
Dd dd = Dd.builder()
.setIntAa(0)
.setIntBb(1)
.setIntCc(2)
.setIntDd(3)
.build();
assertEquals(0, dd.intAa);
assertEquals(1, dd.intBb);
assertEquals(2, dd.intCc);
assertEquals(3, dd.intDd);
}
abstract static class Aa {
int intAa;
static class AaBuilder<B extends AaBuilder> {
int intAa;
Aa build(Aa aa) {
aa.intAa = intAa;
return aa;
}
B setIntAa(int i) {
this.intAa = i;
return (B) this;
}
}
}
abstract static class Bb extends Aa {
int intBb;
static class BbBuilder<B extends BbBuilder<B>>
extends AaBuilder<B>
{
int intBb;
Bb build(Bb bb) {
bb = (Bb) super.build(bb);
bb.intBb = intBb;
return bb;
}
B setIntBb(int i) {
this.intBb = i;
return (B) this;
}
}
}
static class Cc extends Bb {
int intCc;
static CcBuilder<?> builder() {
return new CcBuilder<>();
}
static class CcBuilder<B extends CcBuilder<B>>
extends BbBuilder<B>
{
int intCc;
Cc build() {
return build(new Cc());
}
Cc build(Cc cc) {
cc = (Cc) super.build(cc);
cc.intCc = intCc;
return cc;
}
B setIntCc(int i) {
this.intCc = i;
return (B) this;
}
}
}
static class Dd extends Cc {
int intDd;
static DdBuilder<?> builder() {
return new DdBuilder<>();
}
static class DdBuilder<B extends DdBuilder<B>>
extends CcBuilder<B>
{
int intDd;
Dd build() {
return build(new Dd());
}
Dd build(Dd dd) {
dd = (Dd) super.build(dd);
dd.intDd = intDd;
return dd;
}
B setIntDd(int i) {
this.intDd = i;
return (B) this;
}
}
}
}

Why couldn't I deal with argument in java?

I'm java virgin. I've made really simple code like below.
class TreeData implements Comparable<TreeData> {
private String sixString;
private ArrayList<Integer> stringNum = new ArrayList<Integer>();
private ArrayList<Integer> charNum = new ArrayList<Integer>();
public TreeData(String sixString, int stringNum, int charNum){
this.sixString = sixString;
(this.stringNum).add(stringNum);
(this.charNum).add(charNum);
}
public int compareTo(TreeData other) {
return sixString.compareTo(other.getSixString());
}
public String getSixString(){
return sixString;
}
}
class Child<T extends Comparable<T>>{
public void print(T data){
//error : String a = data.getSixString();
System.out.println("hi");
}
}
public class Test {
public static void main(String[] args) {
Child<TreeData> child = new Child<TreeData>();
TreeData td = new TreeData("sixString", 8, 2);
child.print(td);
}
}
I had a problem in 'print' method in the Child class. When I tried calling the getSixString() method of data(passed as argument), it occurs error. I don't know why I can't using public method in the argument 'data'. Is it related with Generic? Thanks, in advance.
In your Child class, you only define T to be extending Comparable. Yet you expect it to have the method getSixString which Comparable doesn't have. What you probably want it for it to be extending TreeData:
class Child<T extends TreeData>{
public void print(T data){
String a = data.getSixString();
//should work now since T defines getSixString()
}
}
Or better yet if all you want is for T to be TreeData, you don't need any generic class. I'm assuming your real intention was:
class Child extends TreeData {
public void print(){
String a = getSixString();
}
}

Inheritance in Java

Consider the following code in Python:
class A(object):
CLASS_ATTRIBUTE = 42
def f(self):
return "CLASS_ATTRIBUTE: %d" % self.CLASS_ATTRIBUTE
class B(A):
CLASS_ATTRIBUTE = 44
Now A().f() and B().f() return "CLASS_ATTRIBUTE: 42" and "CLASS_ATTRIBUTE: 44" respectively.
How can I achieve a similar effect in Java? I want a CLASS_ATTRIBUTE field to be initialized statically and redefined in the inherited class but the f method should be only defined in the base class.
Is there a particular reason you want the attribute to be static? In Java the typical way you'd do this is to have A contain a protected variable that you then set in the constructors of the 2 classes:
public class A
{
protected int CLASS_ATTRIBUTE;
public A()
{
CLASS_ATTRIBUTE = 42;
}
public String f()
{
return "CLASS_ATTRIBUTE: " + CLASS_ATTRIBUTE;
}
}
public class B extends A
{
public B()
{
CLASS_ATTRIBUTE = 44;
}
}
Alternatively (and probably more consistent with Java design patterns) you'd declare a function that you can override to return the value instead of using a member variable.
Short answer: you cant solve it like this in Java. You'll have to solve it in another way.
In Java you can't override or "redeclare" fields in subclasses, and you can't override static methods.
It can be solved using an ugly reflection-hack (should be avoided though):
public class Main {
public static void main(String... args) {
A a = new A();
B b = new B();
System.out.println(a.f()); // Prints 42.
System.out.println(a.fReflection()); // Prints 42.
System.out.println(b.f()); // Prints 42.
System.out.println(b.fReflection()); // Prints 44.
}
}
class A {
static int CLASS_ATTRIBUTE = 42;
public int f() {
return CLASS_ATTRIBUTE;
}
public int fReflection() {
try {
return getClass().getDeclaredField("CLASS_ATTRIBUTE").getInt(null);
} catch (Exception wontHappen) {
return -1;
}
}
}
class B extends A {
// Compiles, but will not "override" A.CLASS_ATTRIBUTE.
static int CLASS_ATTRIBUTE = 44;
}
You can't do this directly with only a variable, because in Java variables cannot override (they only shadow the super classes variables).
You need to use a protected "getter" method, which can then be overridden by the subclass:
class A
{
private int attribute=42;
...
protected int getAttribute() {
return attribute;
}
}
class B
extends A
{
private int attribute=44;
...
protected int getAttribute() {
return attribute;
}
}
But note there's a special consideration to calling methods from an object's constructor, in that it allows object code to run before object construction is complete.
I'm not sure if you meant "statically" literally or not, but here's a brief example of how inheritance at it's most basic form looks in Java. Note that using a getter method to access the variable is a better idea for several reasons -- this is just an example.
public class Dog {
protected String whatISay = "Woof!";
public void speak(){
System.out.println(whatISay);
}
}
public class Poodle extends Dog {
public Poodle(){
whatISay = "Yap!";
}
}
public class Main {
public static void main(String[] args){
Poodle fluffy = new Poodle();
fluffy.speak();
Dog dog = new Dog();
dog.speak();
}
}
Yap!
Woof!
This way of doing it introduces as little intrusion as I could think of. setAttribute() could be named something like setDefaultValue() if that's clearer.
public class A
{
protected int attribute;
public A()
{
setAttribute();
}
public String f()
{
return "CLASS_ATTRIBUTE: " + attribute;
}
protected void setAttribute()
{
attribute = 42;
}
}
public class B extends A
{
#Override
protected void setAttribute()
{
attribute = 44;
}
}
public class Main
{
public static void main(String[] args)
{
A a = new A();
B b = new B();
System.out.println("A: " + a.f());
System.out.println("B: " + b.f());
}
}

Categories

Resources