I have a few classes which represent arithmetic operations (Plus, Minus, Pow...) in Java which extend the same abstract class Operator but they differ in one method -calculate.
I'm trying to find a way to avoid the switch-case conditions in order to implement these classes in the right way using design patterns (new to design patterns), but how do I do it? Or is the switch-case statement is the right way to implement it?
here is the abstract class:
public abstract class Operator {
private int a, b;
public Operator(int a, int b){
this.a = a;
this.b = b;
}
public float calculate() {
// here I want to return the result depending on the operator. If Plus extends Operator then the returned value is this.a + this.b
}
public void print() {
System.out.println("This is the result : %f", this.calculate());
}
}
In this case there is no need for a design pattern but using polymorphism is enough. Change the Operator class like the following:
public abstract class Operator {
protected int a;
protected int b;
public Operator(int a, int b){
this.a = a;
this.b = b;
}
public abstract float calculate();
public void print() {
System.out.println("This is the result : " + this.calculate());
}
}
And then implement it with Minus and Plus classes:
public class Plus extends Operator{
public Plus(int a, int b) {
super(a, b);
}
#Override
public float calculate() {
return this.a + this.b;
}
}
public class Minus extends Operator{
public Minus(int a, int b) {
super(a, b);
}
#Override
public float calculate() {
return this.a - this.b;
}
}
This is the class Main for a test:
public class Main {
public static void main(String[] args) {
Operator minus = new Minus(5,2);
minus.print(); // prints: This is the result : 3.0
Operator plus = new Plus(5,2);
plus.print(); // prints: This is the result : 7.0
}
}
Please see below code:
Change your calculate method to:
public float calculate(){
// here I want to return the result depending on the operator. If Plus extends Operator then the returned value is this.a + this.b
if(this instanceof Plus ){
return a + (float)b;
}else if(this instanceof Minus ){
return a - (float)b;
}//...For Mul and Div you can code
return 0.0f;
}
and after that, you can change your print method to:
public void print() {
System.out.println(String.format("This is the result : %f", this.calculate()));
}
and after that, you can do call this from any class to get your result:
Operator operator = new Plus(2,5);
operator.print();
operator = new Minus(5,2);
operator.print();
Lastly output:
This is the result: 7.000000
This is the result: 3.000000
Related
I have two interfaces in Java (version 8) which are very similar.
I cannot change the interfaces and cannot change the classes which implement them.
public interface A {
int get();
}
public interface B {
int get();
int somethingelse();
}
Now I have a function that its implementation fits both interfaces (almost).
I want it to do something like that:
public int foo((A | B) p) {
int ret = 0;
if (p instanceof B) {
ret = p.somthingelse();
}
return ret + p.get();
}
I don't want to use inspection because this function is on the main pipeline of my program.
I want it to have good performance.
Is it possible to do this in Java?
Edit:
A simple solution will be to copy/paste foo() and implement it differently for each interface.
But in reality foo() and the interfaces are much longer than that and I'm trying to avoid code duplication.
There's unfortunately no way to create that kind of retroactive relationship between two unrelated types.
If you can change foo() and its invocations, you could be able to make use of functional interfaces matching the signatures that you invoke inside foo. I'm using IntSupplier here, with corresponding lambda expressions using concrete implementations of A and B.
Say you have these implementations:
class AImpl implements A {
//implementation
}
class BImpl implements B {
//implementation
}
You can change foo to something like:
public int foo(IntSupplier get, IntSupplier somethingElse) {
int ret = 0;
if (somethingElse != null) {
ret = somethingElse.getAsInt();
}
return ret + get.getAsInt();
}
And call it this way:
A a = new AImpl();
B b = new BImpl();
int result = this.foo(a::get, b::somethingelse);
The only way I can imagine is this:
public int foo(A p) {
return internal_foo(p);
}
public int foo(B p) {
return internal_foo(p);
}
private int internal_foo(Object p) {
if (p instanceof A) {
return ((A)p).get();
}
if (p instanceof B) {
B b = (B)p;
ret = b.somthingelse();
return ret + b.get();
}
throw new ClassCastException("Wrong type");
}
Afaik, Java doesn't support this directly, but you could manually create a "type-union wrapper". Something like this:
abstract class AorB {
public static AorB wrap(A a) {
return new AWrapper(a);
}
public static AorB wrap(B b) {
return new BWrapper(b);
}
abstract int get();
abstract int somethingElse();
}
class AWrapper extends AorB {
private final A a;
AWrapper(A a) {
this.a = a;
}
#Override
int get() {
return a.get();
}
#Override
int somethingElse() {
return 0;
}
}
class BWrapper extends AorB {
private final B b;
BWrapper(B b) {
this.b = b;
}
#Override
int get() {
return b.get();
}
#Override
int somethingElse() {
return b.somethingElse();
}
}
// and then
public int foo(A a) {
return fooImpl(AorB.wrap(a));
}
public int foo(B b) {
return fooImpl(AorB.wrap(b));
}
int fooImpl(AorB p) {
return p.get() + p.somethingElse();
}
You could also add some inspection functions like hasSomethingElse(), if there's no appropriate default value to return, like the 0 above..
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I want to make sum of two numbers. But I have problems to do that. I don't understand why my sum is always zero.
class A
public class A {
int a=3 ,b=4;
public static void main(String[] args) {
B obj= new B();
obj.prod();
}
}
CLASS B
public class B {
int a, b;
public void prod()
{
System.out.print(a+b);
}
}
Uninitialized primitive fields have a default value. In the case of int this value is 0.
To pass the values from class A to B you should implement a constructor which takes two arguments.
public class B {
int a, b;
public B(int a, int b)
{
this.a = a;
this.b = b;
}
public void prod()
{
System.out.print(a+b);
}
}
Then in your class A, call the constructor of B like this:
public class A {
int a=3 ,b=4;
public static void main(String[] args) {
B obj= new B(a, b);
obj.prod();
}
}
Another way is to give your method prod() the parameters:
public void prod(int a, int b)
{
System.out.print(a+b);
}
And then call it:
public class A {
int a=3 ,b=4;
public static void main(String[] args) {
B obj= new B();
obj.prod(a, b);
}
}
public class A {
int a=3 ,b=4;
public static void main(String[] args) {
B obj= new B();
obj.prod(a,b);
}
}
public class B {
public void prod(int a, int b)
{
System.out.print(a+b);
}
}
I think the below code will help you:
public class A {
public static void main(String[] args) {
// create object B, passing aa=3, bb=4 to B's constructor
B objectB = new B(3, 4);
// this will return result as "12"
int result = objectB.prod();
}
}
public class B {
// declare member variables
private final int a;
private final int b;
// B's constructor
public B (int aa, int bb) {
// set values passed in to member variables
this.a = aa;
this.b = bb;
}
public int prod() {
int result = this.a + this.b;
// print result
System.out.print(result + "");
// return result to caller
return result;
}
}
You are initializing the values in class A. These are not available in class B. Either pass in constructor of class B or pass to the method prod().
You need to modify your class as below :
public class A {
int a = 3, b = 4;
public static void main(String[] args) {
B obj = new B(a, b);
obj.prod();
}
}
public class B {
int a, b;
b(int a, int b) {
this.a = a;
this.b = b;
}
public void prod() {
System.out.print(a + b);
}
}
//OR
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
public class A {
int a = 3, b = 4;
public static void main(String[] args) {
B obj = new B();
obj.prod(a, b);
}
}
//CLASS B
public class B {
int a, b;
public void prod(int a, int b) {
System.out.print(a + b);
}
}
error: mul(int,int) has protected access in Multiplication
Thoughts on what I'm doing wrong?
public class Multiplication{
protected int mul(int a,int b){
return (a*b);
}
}
class ImplimentPkg extends Multiplication {
public static void main(String args[]){
Multiplication obj=new ImplimentPkg();
//Here's the error
System.out.println(obj.mul(2,4));
}
protected int mul(int a,int b){
System.out.println("");
return 0;
}
}
Java tutorial says:
The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.
You may think you have matched the second case(inheritence).
Multiplication obj = new ImplimentPkg();
System.out.println(obj.mul(2, 4));
This means you are using an instance of parent class Multiplication. Although the code is inside a method of subclass of Multiplication. It doesn't mean the instance obj has something to do with inheritance. And of course the mul(...) method is invisible. What you can do is: use keyword super.
public void bar() {
Multiplication mul = new Multiplication();
mul.mul(1, 2); // <- error
super.mul(1, 2); // correct
Multiplication.foo(); // correct
}
Note: if you have protected static method in parent class, like:
public class Multiplication {
private String name = "some";
protected int mul(int a, int b) {
return (a * b);
}
protected static void foo() {
System.out.println("foo");
}
}
Here the foo() method can be accessed everywhere in subclass, but not other classes. By the way, you shouldn't use protected static method, see reasons here.
Another related topic may be interested to you, see here.
Create each class in its own Java file
ImplimentPkg.java
package my;
class ImplimentPkg extends Multiplication {
public static void main(String args[]) {
Multiplication obj = new ImplimentPkg();
System.out.println(obj.mul(2, 4));
}
protected int mul(int a, int b) {
System.out.println("");
return 0;
}
}
Multiplication.java
package my;
public class Multiplication {
protected int mul(int a, int b) {
return (a * b);
}
}
I've been using multiple methods, but my "java the complete reference" book doesn't do a good job of explaining how to use the "this" keyword.
this in java
It is used to refer to the data members of the object in the envoked method or constructor in case there is a name conflict between fields and local variables
public class Test {
String s;
int i;
public Test(String s, int i){
this.s = s;
this.i = i;
} }
It is used to invoke one constructor from another constructor of the same class or you can say constructor chaining.
public class ConstructorChainingEg{
String s;
int i;
public ConstructorChainingEg(String s, int i){
this.s = s;
this.i = i;
System.out.println(s+" "+i);
}
public ConstructorChainingEg(){
this("abc",3); // from here call goes to parameterized constructor
}
public static void main(String[] args) {
ConstructorChainingEg m = new ConstructorChainingEg();
// call goes to default constructor
}
}
It also facilitates method chaining
class Swapper{
int a,b;
public Swapper(int a,int b){
this.a=a;
this.b=b;
}
public Swapper swap() {
int c=this.a;
this.a=this.b;
this.b=c;
return this;
}
public static void main(String aa[]){
new Swapper(4,5).swap(); //method chaining
}
}
Here's a couple:
public class Example {
private int a;
private int b;
// use it to differentiate between local and class variables
public Example(int a, int b) {
this.a = a;
this.b = b;
}
// use it to chain constructors
public Example() {
this(0, 0);
}
// revised answer:
public int getA() {
return this.a;
}
public int getB() {
return this.b
}
public int setA(int a) {
this.a = a
}
public void setB(int b) {
this.b = b;
}
}
this refers to the attributes that belong to the object in which this is used in. For example:
Example ex1 = new Example(3,4);
Example ex2 = new Example(8,1);
In these cases, ex1.getA() will return 3, because this is referring to the a that belongs to the object named ex1, and not ex2 or anything else. The same goes for ex2.getB().
If you look at the setA() and setB() methods, using this distinguishes the attributes a and b belonging to the object from the parameter names as they're the same.
My problem is with the return statement in each method,the error in netbeans says:
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - bad operand types for binary operator '+'
first type: T
second type: T
at GenericMath.add(GenericMath.java:8)
at GenericMath.main(GenericMath.java:20)
public class GenericMath<T> {
public T a,b;
public T add() {
return a+b;
}
public T multiply() {
return (a*b);
}
public static <T> void main(String[] args) {
GenericMath<Integer> x=new GenericMath<Integer>();
x.a=5;
x.b=10;
int z=x.add();
GenericMath<Double> y = new GenericMath<Double>();
y.a = 5.5;
y.b = 10.2;
double g=y.multiply();
}
}
The compiler doesn't know that you can multiply and add T values - it's not the return part which the problem, it's the expression itself. You'll see the same effect if you split the two parts:
T result = a + b;
return result;
It will be the first line that fails - and there's no particularly clean answer to this. Generics just aren't built for this sort of work in Java. What you could do is have:
public abstract class GenericMath<T extends Number> {
public abstract T add(T a, T b);
public abstract T multiply(T a, T b);
// etc
}
public final class IntegerMath extends GenericMath<Integer> {
public Integer add(Integer a, Integer b) {
return a + b;
}
// etc
}
... and similar classes for DoubleMath etc.
Then:
// Alternatively, have a static factory method in GenericMath...
GenericMath<Integer> math = new IntegerMath();
int x = math.add(5, 2);
You need to do these things:
Bound the generic type to Number
Make the add() etc method abstract and return T
Provide implementations for each type you want to support
Like this:
public abstract class GenericMath<T extends Number> {
public T a,b;
public abstract T add();
public abstract T multiply();
}
public class IntegerGenericMath extends GenericMath<Integer> {
public Integer add() {
return a + b;
}
public Integer multiply() {
return a * b;
}
}
// similar for Double
public static void main(String[] args) {
IntegerGenericMath x=new IntegerGenericMath();
x.a=5;
x.b=10;
int z=x.add();
DoubleGenericMath y = new DoubleGenericMath();
y.a = 5.5;
y.b = 10.2;
double g=y.multiply();
}
There's a lot of auto boxing going on here, which won't work genericly, which is why you need separate classes for each type.