I need a function that accepts both types of arguments and has the same body.
How can I do it?
For example:
// I have:
public someFunction(Pageable input) { the same body }
public someFunction(Sort input) { the same body }
// I need
public someFunction(PageableOrSort input) {the same body}
You can try this way, but this is bad practice:
public void someFunction (Object input){
if (input instanceof Pageable) {
Pageable pageable = (Pageable) input;
/* do something else */ }
if (input instanceof Sort) {
Sort sort = (Sort) input;
/* do something else */
}
You could just create a wrapper object that has a Pageable property and a Sort property:
public Class MyWrapper {
public Sort mySort;
public Pageable myPageable;
}
Then you can set both properties then have your method have a MyWrapper as a parameter.
But what is the reason for wanting a single method? Having an overloaded method is good practice in a situation like this and you can abstract your method body to where there is no much duplicate code depending on the logic.
Assume your function someFunction does something like this
input.doA();
input.doB();
Then create an interface that contains those two methods
interface PageableOrSort {
void doA();
void doB();
}
and define your method as
void someFunction(PageableOrSort input) {
input.doA();
input.doB();
}
And make your classes implement the interface
public class Pageable implements PageableOrSort {
#Override
public void doA() {
//do stuff
}
#Override
public void doB() {
//do stuff
}
}
and the same for the other class. Then you can call the method with any class implementing the interface
Pageable pageable = new Pageable();
//...
this.someFunction(pageable)
Related
I've got next situation:
There is an abstract class
public abstract class SuperClass {
public abstract void getString();
public abstract void method2();
}
public class InheritClass1 extends SuperClass {
#Override
public void getString(){...};
#Override
public void method2(){...};
}
public class InheritClass2 extends SuperClass {
#Override
public void getString{...};
#Override
public void method2(){...};
public void customMethod(){...};
}
There is another class that has a method that accepts SuperClass object as an argument. Depending on what kind of String is returned from getString I perform different actions. My case is that I am trying to call a child method while the object is of parent class:
public class Processor {
public String method(SuperClass type) {
switch (type.getString()) {
case "1":
return "OK"
case "2":
return ((InheritClass2) type).customMethod()
}
}
I do understand that this is BAD DESIGN, could you please help me with finding the best solution for this problem. Maybe generics are suitable in this case somehow. Also the thing is that customMethod() should be a part of not all classes.
Since only some (sub)classes implements customMethod, I would suggest to create an interface that contains this method:
public interface CustomInterface {
public String customMethod();
}
Your SuperClass can then remain just as it is. Only the subclasses/child classes that have customMethod, would then extend your SuperClass as well as implement this CustomInterface. This way, the child classes that do not implement CustomMethod (does not have the method in their class, such as InheritClass1 in your example), also remain just as they are.
Only child classes that have CustomMethod, such as InheritClass2 would then need to change slightly by saying it implements this new interface:
public class InheritClass2 extends SuperClass implements CustomInteface {
// the rest stays the same
}
Then in the section where you want to do the casting, you rather do the following:
public class Processor {
public String method(SuperClass type) {
switch (type.getString()) {
case "1":
return "OK"
case "2":
String s = "";
if (type instance of CustomInterface) {
s = (CustomInterface type).customMethod();
}
return s;
}
}
}
Using the interface in this way will help that you can implement all child classes and not just one as implementing the CustomInterface, and thus, all child classes will work with using instanceof and casting to the interface to call customMethod() - you won't have to handle each child that needs this method separately.
NOTE: Your code is clearly simplified example, it is unclear if the getString() method is just returning an identifier of the child classes in order for you to know which ones you can cast and then call custom Method on... If this is the purpose of your switch and getString methods - to identify which types implement the customMethod() and to call that method, and for any child class that does not have that method to return just "OK" - then you could instead do the following:
public class SubClass1 extends SuperClass implements CustomInterface {
// other mehtods...
public String CustomMethod() { return "SomeString1"; }
}
public class SubClass2 extends SuperClass {
// other methods...
// this subclass does not have the CustomMethod()
}
public class SubClass3 extends SuperClass implements CustomInterface {
// other methods...
public String CustomMethod() { return "SomeString3"; }
}
Then your Processor could look like this:
public class Processor {
public String method(SuperClass type) {
return (type instanceof CustomInterface) ? ((CustomInterface) type).CustomMethod() : "OK";
}
public static void main(String[] args) {
Processor p = new Processor();
SuperClass obj1 = new SubClass1();
SuperClass obj2 = new SubClass2();
SuperClass obj3 = new SubClass3();
System.out.println(p.method(obj1)); // prints: "SomeString1"
System.out.println(p.method(obj2)); // prints: "OK"
System.out.println(p.method(obj3)); // prints: "SomeString3"
}
}
If you don't understand the ternary operator then you can read about it here That's the condition ? exprTrue : exprFalse syntax. It's a short if else statement basically.
You can create an interface, with default custom method implementation, like:
interface A {
default String customMethod() {
return "";
}
}
And abstract class will implement this interface:
public abstract class SupperClass implements A {
public abstract String getString();
public abstract void method2();
}
Bad design will cause you to get bad answers. If you don't want to cast your object to a child object. You could use reflection.
import java.lang.reflect.Method;
public class Processor {
public String method(SuperClass type) {
Method[] methods = type.getClass().getMethods();
for (Method m : methods) {
if (m.getName().equals("customMethod")) {
try {
return m.invoke(type);
} catch (Exception ex) {
// throw
}
}
}
return "OK";
}
}
Depending on your design you could apply:
if (type instanceof InheritClass2.class) return type.customMethod();
or
if (type.getClass() == InheritClass2.class) return type.customMethod();
Problem
I need to perform logic over and over on the results of several methods. The methods can have arbitrary result types. The simple use case looks like this:
A wrapper class with an execute method:
/**
* Wrapper class which executes inner logic, processes the result of that logic and returns the processed result.
*
* #param <T>
*/
public abstract class Wrapper<T> {
/**
* Perform inner logic
*/
public abstract T run();
/**
* Invoke inner logic and process it.
*/
public T execute() {
T result = run();
// TODO: process result
return result;
}
}
And the logic in an inner class, example usage of the Wrapper:
public class WrapperDemo {
/**
* Simple invocation of the inner logic and then the outer logic
*/
public static Boolean testMethod() {
// wrap around logic and execute
return new Wrapper<Boolean>() {
#Override
public Boolean run() {
// TODO: perform logic, simply returning true for now
return Boolean.TRUE;
}
}.execute();
}
public static void main(String[] args) {
// demo method invocation
Boolean result = WrapperDemo.testMethod();
// process result
System.out.println(result);
System.exit(0);
}
}
I'll have to apply this to several 100s of methods.
Question
Does anyone know a more convenient way to code this with less code for testMethod (e. g. maybe annotation)?
If you have Java 8, you could write the following:
public static <T> T execute(Wrapper<T> wrapper) {
return wrapper.execute();
}
And then use it as following:
public static Boolean testMethod() {
return execute(()-> {
return Boolean.TRUE;
});
}
Though I fail to see how this is better than the following:
public static <T> T wrap(T result) {
// Process result
return result
}
And using it like this:
public static Boolean testMethod() {
return wrap(Boolean.TRUE);
}
If you want to use annotations, you should use a tool that allows such reflection to be used. Basic reflection can't be used because then you can't "intercept" the call. Java's Proxy might help, but you're constrained to use interfaces, which is not always what people want.
cglib is a library that removes all that hassle. With that, you can try the following:
#Target(METHOD)
#Retention(RUNTIME)
public #interface Wrap {
}
class Demo {
#Wrap
public Boolean testMethod() {
return Boolean.TRUE;
}
}
class Wrapper {
public <T> T newInstance(Class<T> type) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(type);
enhancer.setCallback(new InvocationHandler(){
#Override public Object invoke(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Object result = proxy.invokeSuper(obj, args);
if (method.isAnnotationPresent(Wrap.class)) {
execute(result);
}
return result;
}
});
return enhancer.create();
}
public void execute(Object result) {
// Add custom behavior to #Wrap-ped methods.
}
}
Then you have to call the wrapper like this:
Demo demo = new Wrapper().newInstance(Demo.class);
demo.testMethod();
Other libraries exist too, like Byte Buddy or Javassist. But be careful because Java 9 is very close and forced those libraries into changing their core business very, very quick, possibly making them unstable.
In Java 8, by combination of lambda and default method, you can achieve similar thing without much change in your API (except you need to make Wrapper an interface instead of abstract class)
public interface Wrapper<T> {
public T run();
default public T execute() {
T result = run();
// TODO: process result
return result;
}
}
Then you can call it by
public static Boolean testMethod() {
Wrapper<Boolean> w = ()-> {return Boolean.TRUE;};
return w.execute();
}
But personally I don't think it make much sense.
If you want to add extra logic around a logic, probably what you need is a little twist:
public class ExtraAction<T> {
Supplier<T> supplier;
public ExtraAction(Supplier<T> supplier) {
this.supplier = supplier;
}
public T execute() {
T result = this.supplier.get();
// some extra processsing
return result;
}
}
so it will be called like
Boolean result = new ExtraAction<>(()->{return Boolean.TRUE}).execute();
Even better, make your logic in Wrapper a Function<X,Y>, and make up something to chain your Supplier and Function together, so it will look like
result = Foo.forInput( ()-> { return logicToGetResult(); })
.doExtra(ExtraAction::whateverAction).result();
at work we do a peer review of code and I found something I don't like and I want to ask about best practice for this particular problem.
We have an interface:
public interface Item {
public String getType();
//some other methods
}
and an implementing class:
public class EmailItem implements Item {
public static final String TYPE = "email";
#Override
public String getType() {
return TYPE;
}
}
and some code that uses the classes:
for (Item item : items) {
if (EmailItem.TYPE.equals(item.getType())) {
isProcessed = Processor.process(item);
} else {
LOGGER.error("Unknown failover type received to process. Type: {}", item.getType());
}
}
At this point we have only one implementing class so checking the type is not necessary but we will add some other implementations and then it would make sense (though switch will be used).
The main issue is that EmailItem has variable TYPE set as public and this variable has also a getter.
Both class and instance of that class should have access to this variable, but having it public static final and accessing it with instance directly doesn't seem right/best practice (although it is technically possible) and when it would be private (as it should) then it won't be accessible from other classes (where for cycle is and static would not make sense at that point).
Through discussion we come up with solution with usage of instanceOf(...) or instance.getClass().getName() and EmailItem.class.getName() but none of them seem elegant to me :).
So finally, my question is what is the most elegant solution for described problem?
Heh, this is my first question here and I hope it makes sense to you ;).
Thinking about it from an OO point of view I'd consider the following approach:
public interface Item {
public boolean process();
//some other methods
}
public class EmailItem implements Item {
#Override
public boolean process() {
// email specific implementation
}
}
public class AnotherItem implements Item {
#Override
public boolean process() {
// another implementation
}
}
for (Item item : items) {
isProcessed = item.process();
}
The way you did it is fine, if you want to do it that way:
The static final variable TYPE lets you treat it as a type constant,
The implementation on the instance lets you check the constant against the return value on the interface.
However, when you find yourself dispatching on a type represented by String or some other value, you are usually going down a wrong path of switch statements in object-oriented code. If you have a choice of action at this point, consider an alternative technique of double dispatch, such as implementing the Visitor Pattern:
interface ItemVisitor {
void visitEmail(EmailItem item);
void visitSms(SmsItem item);
}
interface Item {
void accept(ItemVisitor v);
}
class EmailItem implements Item {
public void accept(ItemVisitor v) { v.visitEmail(this); }
}
class SmsItem implements Item {
public void accept(ItemVisitor v) { v.visitSms(this); }
}
Now you can do this:
class Example implements ItemVisitor {
public void visitEmail(EmailItem item) {
// Do something with an e-mail
}
public void visitSms(SmsItem item) {
// Do something with an SMS
}
public static void main(String[] args) {
Example e = new Example();
for (Item item : ItemSource.getManyItems()) {
item.accept(e);
}
}
}
If all "types" for your Item are known at compile time, you could use an enum like this:
public interface Item {
enum ItemType { MAIL, OTHER; }
public ItemType getType();
//some other methods
}
Having the get set model:
public class exampleclass
{
private Something something;
public Something getSomething()
{
return something;
}
public void setSomething(Something st)
{
something = st;
}
}
I wanna make something like this:
public class exampleclass
{
public Something something;
public void setSomething(Something st)
{
something = st;
}
}
But i want to have "something" var with readOnly feature out of the class (but rewritable in the own class). Any idea of how to do this for an optimized access. (Think this is gonna be used in android , but using a pure java only framework (libgdx) )
You can set thoose things in constructor and expose public final field:
public class ExampleClass
{
public final Something something;
public ExampleClass(Something st)
{
something = st;
}
}
You could use the final keyword.
The you can assign it once.
e.g
public class Exampleclass
{
public final Something something;
void Exampleclass(Something init) {
this.something = init;
}
}
However the content of Something still could be changed, so you may consider returning a clone() of something. (see the class java.util.Date, you still could set the timestamp, in such cases only clone() or a copy constructor helps) . But if your code is not a public lib, then you can leav that getter with clone() away
public class Exampleclass
{
private Something something;
void Exampleclass(Something init) {
this.something = init;
}
void Something getSomething() {
return something.clone();
}
}
But that depends on Something.
Another soultion is a Factory Pattern, such that only the Factory can create Something.
Then there is no public constructor in Something. Only the factory can create it.
public class Something() {
private int value;
protectectd Something(int value) {
this.value = value;
}
public tostring() {
System.out.println("values = " + value);
}
}
public class SomethingFactory() {
protected static Someting createSomething(int value) {
return new Something(value);
}
}
USage:
Something some = SomethingFactory.createSomething(3);
But read more by search "java Deisgn Patterns Factory" or FactoryPattern
I guess your issue is escaping reference, if you want to save your object while returning, send a copy of reference, you can send cloned object using clone method.
public Something getSomething()
{
return something.clone();
}
This will return object shallow copy, if you want make deep cloning override the clone() method Hope this will help..
Here's an example:
class A
{
List l = new List ();
list.insert("x");
}
class List
{
...
public void insert ()
{
/*insertion occurs*/
}
...
}
Is it possible at all to keep the insert() method public, but limit access only to class A so that no other class can access it, only when called from A?
I would pass the object that is calling the method as an argument, i.e.
list.insert("x", this);
And then check if the passed Object is an Instance of Class A
public void insert (String x, Object o)
{
if(o instanceof ClassA){
/*insertion occurs*/
}
}
If the method is public, everyone can access it. The trick to access control like yours is to expose a set of public operations through an interface, add auxiliary operations to a private class implementing the interface, and make your users program to the interface, not to a class.
Here is an example:
public interface MyList {
Object elementAt(int i);
}
public class A {
private static class MyListImpl implements MyList {
public Object elementAt(int i) {
...
}
public void insert(Object element) {
...
}
}
private final MyListImpl list = new MyListImpl();
public MyList getList() { return list; }
public void insert(Object o) { list.insert(o); }
}
Usage scenario:
A a = new A();
a.insert(123);
a.insert("quick brown fox");
MyList lst = a.getList();
System.out.println(lst.elementAt(0));
System.out.println(lst.elementAt(1));
Yes, you can pass calling object as an argument and put a check in insert() method before actual code.
public void insert(Object obj){
if(obj instanceof A){
//your code block
}
}
Please note that this will allow all the classes that extends A as well to call insert. If you want to restrict only for class A, add additional check.
public void insert(Object obj){
if((obj instanceof A) && obj.getClass().getSimpleName().equals("A")){
//your code block
}
}
we can also achieve second case with only condition "obj.getClass().getSimpleName().equals("A")" as well.
The best you can do using access modifiers is to make the method package private (remove the public keyword) and keep only those two classes in the same package.
If all the "inner classes" stuff in the previous answers confuses you, there is another way that may be more intuitive (assuming you've learned about the extends keyword and inheritance). You can simply make the insert() method protected instead of public and make class A extend List. For example:
public class List {
...
protected void insert() {
//insertion occurs
}
...
}
public class A extends List {
...
}
As long as no other classes extend List, only objects of types A and List will ever be able to use the insert() method.
package problems;
public class Problem1 {
public static void main(String[] args) {
B b = new B();
b.methodInB();
C c = new C();
c.methodNotInB();
}
}
class A {
public void onlyB() {
StackTraceElement[] stackTraceElements = Thread.currentThread()
.getStackTrace();
if (!problems.B.class.getCanonicalName().equals(
stackTraceElements[stackTraceElements.length - 2]
.getClassName())) {
System.err.println("You are not authorized to call me!!");
return;
}
System.out.println("You are authorized to call me!!");
}
}
class B {
public void methodInB() {
A a = new A();
a.onlyB();
}
}
class C {
public void methodNotInB() {
A a = new A();
a.onlyB();
}
}
Put it as inner class in A or you can do another thing ...
Let insert takes one parameter with type of Object and in the beginning of it check if the parameter's type is A .... and when you call it send the calling object...
maby its not a good idea but it will do what you want
Put it into the permitted class and make it private.