I have 10 specific methods on my code, and I want to use them with a Class Object like this one:
void function(){
//do Something that I want
}
class PoseAction{
Pose pose;
void methodDesirable();
PoseAction(Pose ps, Method function()){
this.pose = ps;
this.methodDesirable() = function();
}
}
So when I create a new Object
PoseAction ps = new PoseAction(pose1, action1());
calling
ps.methodDesirable();
it will call action1() function.
It's possible to do this?
Thanks in advance!
Functions are not first class objects in java. That is, you can not directly assign them or pass them as method parameters. You need to use objects and interfaces:
interface Action {
void fire(Pose pose);
}
class PoseAction {
Action action;
Pose pose;
void methodDesirable() {
action.fire(pose)
}
PoseAction(Pose ps, Action a) {
pose = ps;
action = a;
}
}
And use it like:
PoseAction ps = new PoseAction(pose1, new Action() {
public void fire(Pose pose) {
action1(pose);
}
};
ps.methodDesirable();
No it's not possible in such way, Java doesn't support delegates. In java that can be done with interfaces:
interface Command {
void doCommand();
}
PoseAction pa = new PoseAction(new Pose(), new Command() {
#Override
public void doCommand() {
//method body
}
});
Here new Command() {...} is anonymous inner class that implements Command Interface
Related
For example, this is valid and we need to have Class Two objects in this T array, what is the purpose of this acceptance?
interface One
{
public void callback();
}
class Two implements One
{
One[] T = new One[5];
}
Because you aren't instantiating an interface, you are instantiating an array. No interfaces are instantiated here:
One[] T = new One[5];
Every element of T will be null. Creating an instance could look like this:
class OneImpl implements One {
#Override
public void callback() {
System.out.println("callback");
}
}
T[0] = new OneImpl();
Or like this:
T[0] = new One() {
#Override
public void callback() {
System.out.println("callback");
}
};
Or even like this:
T[0] = () -> System.out.println("callback");
For studying purpose, I am trying to migrate this Java Command Pattern example to PHP:
https://codereview.stackexchange.com/questions/52110/command-pattern-implementation
As #simon commented, using method reference operator, would modernize quite a bit the code:
class MyCommand implements Order {
private final Runnable action;
public MyCommand(Runnable action) {
this.action = action;
}
#Override
public void execute() {
action.run();
}
}
And then you could create commands like this:
MyCommand bsc = new MyCommand(stock::buy);
MyCommand ssc = new MyCommand(stock::sell);
My current PHP implementation is here: https://3v4l.org/iIHn9
So what is the best approach to implement the MyCommand Class in PHP?
As Evgeniy already mentioned you can use call_user_func().
Since there is many ways how to solve this I've added my solutions to your question. You can also make an object callable by adding the __invoke method inside a class. It's also possible to return a callable function. I've added in total 3 examples for it.
This is my version of your MyCommand class in java which is used for all 3 examples.
class MyCommand implements Order
{
private $action;
public function __construct(callable $action)
{
$this->action = $action;
}
public function execute()
{
// Option 1) use call_user_function
call_user_func($this->action);
// Option 2) define it as a variable and call it by adding `()`
//$action = $this->action;
//$action();
}
}
Example 1) A callable function (https://3v4l.org/FVTEK)
class Stock
{
public function buy(): callable
{
return function () {
echo "You want to buy stocks via callable function" . PHP_EOL;
};
}
public function sell(): callable
{
return function () {
echo "You want to sell stocks via callable function" . PHP_EOL;
};
}
}
$stock = new Stock();
$bsc = new MyCommand($stock->buy());
$ssc = new MyCommand($stock->sell());
$bsc->execute();
$ssc->execute();
Example 2) A callable class (https://3v4l.org/BrKjv)
class StockBuy
{
public function __invoke()
{
echo "You want to buy stocks via __invoke()" . PHP_EOL;
}
}
class StockSell
{
public function __invoke()
{
echo "You want to sell stocks __invoke()" . PHP_EOL;
}
}
$bsc = new MyCommand(new StockBuy());
$ssc = new MyCommand(new StockSell());
$bsc->execute();
$ssc->execute();
Example 3) Static member functions which return callable. Just an example to be more close to java (https://3v4l.org/PKk4B)
class Stock
{
static public function buy(): callable
{
return function () {
echo "You want to buy stocks via callable function" . PHP_EOL;
};
// or as callable object
// return new StockBuy();
}
static public function sell(): callable
{
return function () {
echo "You want to sell stocks via callable function" . PHP_EOL;
};
// or as callable object
// return new StockSell();
}
}
$bsc = new MyCommand(Stock::buy());
$ssc = new MyCommand(Stock::sell());
$bsc->execute();
$ssc->execute();
Please let me know if you have any further questions.
In PHP you can achieve the same using call_user_func that is similar to method reference in Java.
<?php
namespace StockCommandNS;
//Command interface
interface Order {
public function execute();
}
//Receiver class
class StockTrade {
public function buy() {
print("You want to buy stocks\n");
}
public function sell() {
print("You want to sell stocks\n");
}
}
//Invoker class
class Agent {
public function placeOrder(Order $order) {
$order->execute($order);
}
}
//ConcreteCommand Class
class GenericOrder implements Order {
private $action;
public function __construct($action) {
$this->action = $action;
}
public function execute() {
call_user_func($this->action);
}
}
$stock = new StockTrade();
$bsc = new GenericOrder([$stock, 'buy']);
$ssc = new GenericOrder([$stock, 'sell']);
$agent = new Agent();
$agent->placeOrder($bsc); // Buy Shares
$agent->placeOrder($ssc); // Sell Shares
Output for 7.2.0 - 7.4.3
You want to buy stocks
You want to sell stocks
Run PHP code: https://3v4l.org/fWo20
Another less clean option is to use variable function.
class GenericOrder implements Order {
private $stock;
private $action;
public function __construct($stock, $action) {
$this->stock = $stock;
$this->action = $action;
}
public function execute() {
$method = $this->action;
$this->stock->$method();
}
}
$bsc = new GenericOrder($stock, 'buy');
$ssc = new GenericOrder($stock, 'sell');
I'm not sure that the approach with method references is better in all cases.
As a rule of thumb, you should always consider on per-use-case basis when to use method references or anonymous function is the Command pattern.
Here are some references regarding PHP's design patterns:
https://designpatternsphp.readthedocs.io/en/latest/README.html
https://phptherightway.com/#design_patterns
I have these two methods
private void saveBaseLineLatency(E2EResultShort e2EResultShort) {
LatencyHistogram latencyHistogram = getLatencyHistogram(e2EResultShort);
latencyDrillDownRepository.saveBaseLine(latencyHistogram);
saveLatencyTable(latencyHistogram);
}
private void saveFreshTestLatency(E2EResultShort e2EResultShort) {
System.out.println("log: before saveLatencyHistogram");
LatencyHistogram latencyHistogram = getLatencyHistogram(e2EResultShort);
latencyDrillDownRepository.save(latencyHistogram);
saveLatencyTable(latencyHistogram);
}
How can I refactor out their common code?
I thought to use Callable but its call() is parameterless.
Consumer is the interface you want. It's part of the new java.util.function package in Java 8, so this won't work if you're on an older version of Java. (The package also has a number of similar other interfaces, like a BiConsumer that takes two arguments, and interfaces for consuming various primitive types as well.)
So, your helper method would be something like:
private void doLatencyOperation (E2EResultShort newThing, Consumer<LatencyHistogram> consumer) {
LatencyHistogram lh = getLatencyHistogram(newThing);
consumer.accept(lh);
saveLatencyTable(lh);
}
and you could call it thusly
private void saveBaseLineLatency(E2EResultShort e2EResultShort) {
doLatencyOperation(e2EResultShort, (lh) -> latencyDrillDownRepository.saveBaseLine(lh));
}
Create an abstract class and move all the common code there.
public abstract class MyClass{
public MyClass(E2EResultShort result, latencyDrillDownRepository){
this.result = result;
}
public void execute() {
LatencyHistogram latencyHistogram = getLatencyHistogram(e2EResultShort);
callMe(latencyHistogram, latencyDrillDownRepository);
saveLatencyTable(latencyHistogram);
}
public abstract void callMe(LatencyHistogram latencyHistogram, latencyDrillDownRepository);
}`
Now in your method, create concrete MyClass:
private void saveFreshTestLatency(E2EResultShort e2EResultShort) {
System.out.println("log: before saveLatencyHistogram");
MyClass myClass = new MyClass(e2EResultShort, latencyDrillDownRepository){
public void callMe(LatencyHistogram latencyHistogram, latencyDrillDownRepository){
latencyDrillDownRepository.save(latencyHistogram);
}
}
myClass.execute();
}
[EDIT: I've rewritten the code to further simplify it and focus on the issue at hand]
I'm working on this particular piece of code:
class SimpleFactory {
public SimpleFactory build() {return null}
}
class SimpleFactoryBuilder {
public Object build(final Class builderClazz) {
return new SimpleFactory() {
#Override
public SimpleFactory build() {
return new builderClazz.newInstance();
}
};
}
}
However, the builder in the return statement triggers the error "Cannot find symbol newInstance". It's as if builderClazz wasn't recognized as a class object.
How can I make it work?
EDIT: SOLUTION (thanks to dcharms!)
The code above is a partial simplification of the code I was dealing with. The code below is still simplified but includes all the components involved and includes the solution provided by dcharms.
package com.example.tests;
interface IProduct {};
interface ISimpleFactory {
public IProduct makeProduct();
}
class ProductImpl implements IProduct {
}
class SimpleFactoryBuilder {
public ISimpleFactory buildFactory(final Class productMakerClazz) {
return new ISimpleFactory() {
#Override
public IProduct makeProduct() {
try {
// the following line works: thanks dcharms!
return (IProduct) productMakerClazz.getConstructors()[0].newInstance();
// the following line -does not- work.
// return new productMakerClazz.newInstance();
}
catch (Exception e) {
// simplified error handling: getConstructors() and newInstance() can throw 5 types of exceptions!
return null;
}
}
};
}
}
public class Main {
public static void main(String[] args) {
SimpleFactoryBuilder sfb = new SimpleFactoryBuilder();
ISimpleFactory sf = sfb.buildFactory(ProductImpl.class);
IProduct product = sf.makeProduct();
}
}
You cannot instantiate a new object this way. builder is a Class object. Try instead the following:
return builder.getConstructors()[0].newInstance(anInput);
Note: this assumes you are using the first constructor. You may be able to use getConstructor() but I'm not sure how it would behave with the generic type.
I am used to use generics in typed collections, but I never actually used them to develop something.
I have several classes like this:
public class LogInfoWsClient extends GenericWsClient {
public void sendLogInfo(List<LogInfo> logInfoList) {
WebResource ws = super.getWebResource("/services/logInfo");
try {
String response = ws.accept(MediaType.TEXT_HTML).type(MediaType.APPLICATION_XML).put(String.class, new GenericEntity<List<LogInfo>>(logInfoList) {
});
}
}
Where the only thing changing between one and another is the service String ("/services/info"), and the type of the list (LogInfo in this case)
I have refactored a couple of methods to a GenericWsClient class, but my objective would be to have something I can use like this:
List<LogInfo> myList = database.getList();
SuperGenericClient<List<LogInfo>> superClient = new SuperGenericClient<List<LogInfo>>();
superClient.send(myList,"/services/logInfo");
But I cannot figure out how to do it, or even if its possible. Would it be possible?
Yes it is possible infact if you look at java.util.collection package for example you will find all classes to be parameterzid.
So your class will be something like this
public SuperGenericClient<E> {
public E getSomething() {
return E;
}
}
Then to use it you will have
SuperGenericClient<String> myGenericClient = new SuperGenericClient<String>();
String something = myGenericClient.getSomething();
Extending your example itself your code will look like this:
public class SuperGenericClient<E> extends GenericWsClient {
public void send(List<E> entityList, String service) {
WebResource ws = super.getWebResource(service);
try {
String response = ws.accept(MediaType.TEXT_HTML).type(MediaType.APPLICATION_XML).put(String.class, new GenericEntity<E>(entityList) {
});
}
}
}
public class GenericEntity<E> {
public GenericEntity(List<E> list){
}
}
You must read this for a very good understanding of Generics.
You could write your class like the one below - you can apply the same idea to GenericEntity.
public class SuperGenericClient<T> extends GenericWsClient {
public void send(List<T> list, String service) {
WebResource ws = super.getWebResource(service);
try {
String response = ws.accept(MediaType.TEXT_HTML).type(MediaType.APPLICATION_XML).put(String.class, new GenericEntity<T>(list) {
});
}
}
}
You can then call it like that:
List<LogInfo> myList = database.getList();
SuperGenericClient<LogInfo> superClient = new SuperGenericClient<LogInfo>();
superClient.send(myList,"/services/logInfo");
Declare your class like this:
public class LogThing<T> {
public void sendLogInfo(List<T> list) {
// do thing!
}
}
And when you use it, do so like this:
List<LogInfo> myList = db.getList();
LogThing<LogInfo> superClient = new LogThing<LogInfo>();
superClient.sendLogInfo(myList);