I will provide a practical example.
I want to create an event logger. I define an event as an Interface:
import java.util.function.Consumer;
interface Event {}
class BuyEvent implements Event {}
class SellEvent implements Event {}
A logger is simply a Consumer of events:
public static void main(String[] args) {
Consumer<Event> logger;
// Logger with method reference
logger = System.out::println;
logger.accept(new BuyEvent());
// Logger with lambda
logger = (event) -> {
// Do something else
System.out.println(event);
};
logger.accept(new BuyEvent());
I can also create a logger with state. For example:
class StatefulLogger implements Consumer<Event> {
public StatefulLogger() {
}
#Override
public void accept(Event event) {
// Change state, then print event
System.out.println(event);
}
}
I can use the stateful logger as follows:
public static void main(String[] args) {
Consumer<Event> logger = new StatefulLogger("foo.txt");
logger.accept(new BuyEvent());
}
I am trying to achieve the same in Rust.
I define an event as an enum:
#[derive(Debug)]
enum Event {
BuyEvent,
SellEvent,
}
I define a Logger trait and a struct with state that implements such trait:
trait Logger {
fn accept(&mut self, ev: Event);
}
struct StatefulLogger {}
impl Logger for StatefulLogger {
fn accept(&mut self, ev: Event) {
// Change state, then print event
println!("{:?}", ev);
}
}
I can use the logger as follows:
fn main() {
let logger: &dyn Logger = &ComplexLogger {};
}
I would like to be able to assign a closure to the logger, much in the same spirit of Java.
fn main() {
let consumer: fn(Event) = |ev: Event| {
println!("{:?}", ev);
};
}
To recap:
In Java, I had implemented a logger using a Strategy design pattern using the Consumer interface. A logger could both be a complex stateful object but also a lightweight lambda.
I would like to achieve the same in Rust, but I don't know how to proceed. I was not able to find similar examples on the Internet. Also, does Rust provide an analogous to Java's Consumer interface?
There is no way to solve this fast in Rust, but you can create own macro to convert lambda to Logger impl and then return its object. Have a look at this repo. If you want, I can write a solution soon.
In other way you can change your Logger trait to struct, where define field for consumer. It gives you possibility to use as consumer any Fn(Event) i.e if you have logger with state, you can move it to lambda and pass it or pass some fn directly.
#[derive(Debug)]
struct Event;
struct Logger<T>
where
T: Fn(Event),
{
consumer: T,
}
impl<T> Logger<T>
where
T: Fn(Event),
{
fn new(consumer: T) -> Self {
Self { consumer }
}
fn accept(&self, event: Event) {
(self.consumer)(event);
}
}
struct StatefulLogger;
impl StatefulLogger {
fn log(&self, event: Event) {
println!("{:?}", event);
}
}
fn log_fn(e: Event) {
println!("{:?}", e);
}
fn main() {
let foo = |e: Event| println!("{:?}", e);
let logger_lambda = Logger::new(foo);
let stateful_logger = StatefulLogger;
let logger_struct = Logger::new(move |e| stateful_logger.log(e));
let logger_fn = Logger::new(log_fn);
logger_lambda.accept(Event);
logger_struct.accept(Event);
logger_fn.accept(Event);
}
About consumer interface, have a look on Fn, FnMut and FnOnce traits.
Related
I have this class that wraps an object:
public class MyWrapper implements MyInterface {
private MyInterface wrappedObj;
public MyWrapper(MyInterface obj) {
this.wrappedObj = obj;
}
#Override
public String ping(String s) {
return wrappedObj.ping(s);
}
#Override
public String doSomething(int i, String s) {
return wrappedObj.doSomething(i, s);
}
// many more methods ...
}
Now I want to add complex exception handling around the wrappedObj call.
It is the same for all the methods.
How do I avoid repeating the same exception handling code over and over?
If your exception handling is fully generic you could implement the wrapper as InvocationHandler:
public class ExceptionHandler implements java.lang.reflect.InvocationHandler {
public ExceptionHandler(Object impl) {
impl_ = impl;
}
#Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
return method.invoke(impl_, args);
}
catch (Exception e) {
// do exception handling magic and return something useful
return ...;
}
}
private Object impl_;
}
and then wrap it around an instance as follows:
MyInterface instance = ...
MyInterface wrapper = (MyInterface)java.lang.reflect.Proxy.newProxyInstance(
instance.getClass().getClassLoader(),
new Class[] { MyInterface.class },
new ExceptionHandler(instance));
wrapper.ping("hello");
If you want to avoid the cost of reflection, than just use a router function.
#Override
public String ping(String s) {
return (String) call("ping");
}
private Object call(String func) {
try {
switch(func) {
case "ping": return wrappedObj.ping(s);
// ... rest of functions ... //
}
} catch(Exception e) {
log(e);
}
}
The compiler can than effectively just jump to the function without pulling up Object specs or handlers. (A smart enough compiler may even just compile this to identical execution code as your current code, especially if you can cut the cast by always returning the same kind of object)
If you don't care about the thread and just want a default exception handler...
For the whole Java Runtime, call Thread.setDefaultUncaughtExceptionHandler
For a ThreadGroup, override ThreadGroup.uncaughtException
For a single Thread, call Thread.setUncaughtExceptionHandler
The advantage to a default handler, is that you can then add specific error handlers where needed, but the down side is you do lose the executing thread on error.
I am having the following problem. I have implemented a pipeline processing and sometimes I have to release resources like for example Files. At the same time my pipeline is asynchronous so it immediately releases control I am having a shutdown method in the Non-lamda implementation. I am not able to plug it in using lambdas. My current code looks like this:
#FunctionalInterface
public interface Stage<T,Q> {
public Q process(T toProcess);
}
#FunctionalInterface
public interface IntermediatStage<T,Q> extends Stage<T,Q> {
public default <P> IntermediatStage<T,P> nextStage(Stage<Q,P> nextStage) {
return (T t) -> {return nextStage.process(this.process(t)); };
}
}
I need to subsequently call a shutdown method on the different stages. The problem is that chaining them by a default method I don't have visibility on them. Is it possible somehow when I add the Stages to also be able to add a shutdown hook which I can call independently later based on the fact that the pipeline is asynchroneus ?
Thanks
You can’t solve everything with interfaces and lambda expressions only. This looks like a simple task for an ordinary class having a pattern like this:
public final class Stage<T,R> {
static final Runnable NO_OP = () -> {};
public static <I,O> Stage<I,O> create(Function<I,O> f) {
return new Stage<>(f, NO_OP);
}
public static <I,O> Stage<I,O> create(Function<I,O> f, Runnable cleanup) {
return new Stage<>(f, cleanup);
}
private final Function<T,R> actualAction;
private final Runnable cleanup;
private Stage(Function<T,R> f, Runnable r) {
actualAction=f;
cleanup=r;
}
public <P> Stage<T,P> nextStage(Function<R,P> nextStage) {
return new Stage<>(actualAction.andThen(nextStage), cleanup);
}
public <P> Stage<T,P> nextStage(Function<R,P> nextStage, Runnable nextCleanup) {
return new Stage<>(actualAction.andThen(nextStage),
cleanup==NO_OP? nextCleanup: () -> { cleanup.run(); nextCleanup.run(); });
}
public R process(T t) {
return actualAction.apply(t);
}
public Function<T, R> getActualAction() {
return actualAction;
}
public void cleanup() {
cleanup.run();
}
public Runnable getCleanup() {
return cleanup;
}
}
The Stage class is simple and invariant, but it’s actual behavior is determined by the Function and Runnable instances which can be created via lambda expression, if you wish. You can create and chain either, using a plain function only or by providing a function and a cleanup action. You’ll get two different chains for the functions and cleanup actions, thus can execute them independently.
Without more information about how resources are cleaned up, one could imagine something like
#FunctionalInterface
public interface Stage<T,Q> {
Q process(T toProcess);
static <T,Q> Stage<T,Q> of(Stage<T,Q> stage){
return stage;
}
default Stage<T,Q> withRelease(Consumer<T> releaser){
return t -> {
Q q = process(t);
releaser.accept(t);
return q;
};
}
}
which you could invoke like
Stage.of(Thing::process).withRelease(Thing::close)
I am trying to use RabbitMQ and based on different message, different implements should be called.
I set the message format as of JSON, and there is a field "callType", the value of it is the class name implements a common interface. e.g, all implementations have implements interface "Task", and I have implementation of "TaskImp1","TaskImp2","TaskImp3".
So the code should be like
if (callType=="TaskImp1")
((Task)TaskImp1).runTask()
if (callType=="TaskImp2")
((Task)TaskImp2).runTask()
if (callType=="TaskImp3")
((Task)TaskImp3).runTask()
But could it be more flexible? If later I develop a new one "TaskImp4", I don't want to change the calling code, is it possible to have java automatically pick the right implementation since the callType is actually the class name of the implementation.
Yes, for example, through Java reflection (What is reflection and why is it useful?). Reflection has a performance cost though (Java Reflection Performance)
Sure: put your Task instances in a map:
private Map<String, Task> tasksByName = new HashMap<>();
...
tasksByName.put("TaskImp1", new TaskImp1());
tasksByName.put("TaskImp2", new TaskImp2());
tasksByName.put("TaskImp3", new TaskImp3());
...
String callType = message.getCallType();
Task task = tasksByName.get(callType);
task.runTask();
Also, read How do I compare strings in Java?
You have an opportunity to use Strategy here. So for e.g. you could do like:
public class MyTask {
private Task task;
public MyTask(Task task) {
this.task = task;
}
public void doSomething() {
task.runTask();
}
public static void main(String args[]) {
MyTask task = new MyTask(new TaskImpl1());//or even you could use setTask() api to inject task at runtime rather than doing cast on compile time.
task.doSomething();
task = new MyTask(new TaskImpl2());
task.doSomething();
task = new MyTask(new TaskImpl3());
task.doSomething();
}
}
In this way you could make your code extensible. Tomorrow if you have taskImpl4, you could code it independently and inject in MyTask without even touching MyTask class implementation.
As #ovdsrn already said you can use reflection. Simple example would be something like (the key is getTask static method. Also, note that, when you are using Class.forName you must specify whole "path" (package) for your class)
// ITask.java
package main;
public interface ITask {
void doSomething();
}
// Task1.java
package main;
public class Task1 implements ITask {
#Override
public void doSomething() {
System.out.println("Task1");
}
}
// Task2.java
package main;
public class Task2 implements ITask {
#Override
public void doSomething() {
System.out.println("Task2");
}
}
// main
package main;
public class JavaTest {
private static ITask getTask(String name) {
try {
Class<?> cls = Class.forName(name);
Object clsInstance = (Object) cls.newInstance();
return (ITask)clsInstance;
} catch (Exception e) { // you can handle here only specific exceptions
return null;
}
}
public static void main(String[] args) {
String name = args.length > 0 ? args[0] : "Task2";
ITask task = getTask("main." + name);
if (task != null) {
task.doSomething();
}
else {
System.out.println("can not make instance of class: " + name);
}
}
}
Assume an initial scenario, following which I would be the modified problematic case.
interface Logger {
log() { }
}
class LogFile extends Logger {
log() { // log to file }
}
class LogDB extends Logger {
log() { // insert log into DB }
}
Now LogDB changes into something like:
class LogDB {
logMySQL() { };
logMongo() { };
}
How can this change be incorporated into LogDB while I still want it to fit into Logger interface ?
I think it's better to make two subclasses of the LogDB class - one for dealing with MongoDB and one for MySQL.
class LogMongoDB extends LogDB {
#Override
log() {
//persist the log in MongoDB
}
}
class LogMySQL extends LogDB {
#Override
log() {
//persist the log in MySQL
}
}
If LogDB needs to implement Log, but must also do some customized logging, add a function that does the generic logging activity, as required by the interface, and call it from each customized version (or vice-versa, depending on your needs):
public void log() {
//Common logging stuff here
}
public void logDB() {
//Database-specific logging here...
log();
}
public void logMongo() {
//Mongo-specific logging here...
log();
}
But as stated by #kocko, you seem to be mashing two types of logging into one object, which is why you're asking the question in the first place. Split it up as he suggests, then you won't have this problem to begin with.
I'd do it differently, not with inheritance, but with composition.
interface Logger {
log(String message) { }
}
class LogFile extends Logger {
public LogFile(File file) {}
log(String message) { /* log to file */ }
}
class LogDB extends Logger {
private DBLogConf dbConf;
private DBAbstractionLayer dbal;
public LogDB(IDBLogConf dbConf, IDBAbstractionLayer dbal) {
this.dbConf = dbConf;
this.dbal = dbal;
}
log(String message) {
List<String> fields = new ArrayList<String>();
fields.add(dbConf.getLogField());
List<String> values = new ArrayList<String>();
fields.add(message);
dbal.insert(dbConf.getContainer(), fields, values);
}
}
interface IDBLogConf {
public String getContainer(); // table or document
public String getLogField();
}
class DBLogConf implements IDBLogConf { /* ... */ }
interface IDBAbstractionLayer {
public void insert(String container, List<String> fields, List<String> values) {
// ...
}
// other methods
}
class JDBCAbstractionLayer implements IDBAbstractionLayer {
private Connection conn;
public JDBCAbstractionLayer(Connection conn) {
this.conn = conn;
}
public function insert(...) { /* ... */}
}
abstract class NoSQLAbstractionLayer implements IDBAbstractionLayer {
// ...
}
class MongoAbstractionLayer extends NoSQLAbstractionLayer {
// ...
}
Putting this all toghether:
IDBConf dbConf = new DBConf('log_table', 'details');
IDBAbstractionLayer dbal = new JDBCAbstractionLayer(/* some JDBC connection, */);
Logger dbLogger = new LogDb(dbConf, dbal);
dbLogger.log("Something");
Logger fileLlogger = new LogFile(new File('/var/log/my_log'));
fileLogger.log("Something");
However this seems more complex than the above examples, this implementation does not violate SRP and avoids code duplication.
I've recently started using C#, and I wanted to find an equivalent method to this. I do not know what this is called, so I will simply show you by code.
With Java, I was able to create an interface like so:
public interface Event {
public void execute();
}
And pass this interface in a method's parameter like so:
public class TestEvent {
ArrayList<Event> eventList = new ArrayList<Event>();
public void addEvent(Event event){
eventList.add(event);
}
public void simulateEvent(){
addEvent(new Event() {
public void execute(){
//functionality
}
} );
}
public void processEvents(){
for(Event event : eventList)
eventList.execute();
}
}
EDIT : My question is revolved on the simulatEvent method from the TestEvent class, and if such an action is possible with C#.
I wanted to know if there was a way to do something similar to this with C#, (instantiating the interface in the simulateEvent method) and what this is actually called. Thank you!
Woof...ok, permit me to generalize a bit:
So in Java, you need a way to pass functions around. Java does not inherently support functions as first-class citizens, and this was one reason behind the implementation of anonymous classes - packaged groups of functions that can be declared inline and passed (as interfaces) to methods/other classes that will then call these functions.
In C#, functions are first-class citizens, and can be declared as either Delegates, Func<>s, or Action<>s. Let's try a comparison (of sorts):
Some sort of Java-y construct (my Java's fairly old, so bear with me):
public interface IDoSomething {
public int Return42();
public bool AmIPrettyOrNot(string name);
public void Foo();
}
public void Main(String[] args) {
DoStuff(new IDoSomething() {
public int Return42() { return 42; }
public bool AmIPrettyOrNot(string name) { return name == "jerkimball"; }
public bool Foo(int x) { ... }
});
}
public void DoStuff(IDoSomething something) { ... }
The (very rough) equivalent of this in C# would be:
public void Main(string[] args)
{
Func<int> returns42 = () => 42;
Func<string,bool> amIPretty = name => name == "jerkimball";
Action<int> foo = x => {};
}
Now, as others have mentioned, you usually see this pattern on the Java side when dealing with the handling of events - likewise on the C# side:
public class Foo
{
// define the shape of our event handler
public delegate void HandlerForBarEvent(object sender, EventArgs args);
// declare our event
public event HandlerForBarEvent BarEvent;
public void CallBar()
{
// omitted: check for null or set a default handler
BarEvent(this, new EventArgs());
}
}
public void Main(string[] args)
{
var foo = new Foo();
// declare the handler inline using lambda syntax
foo.BarEvent += (sender, args) =>
{
// do something with sender/args
}
foo.CallBar();
}
Note that we can also give it something with the same "shape":
public void MyHandler(object sender, EventArgs args)
{
// do stuff
}
public void Main(string[] args)
{
var foo = new Foo();
// that method above is the same "shape" as HandlerForBarEvent
foo.BarEvent += MyHandler;
foo.CallBar();
}
But it's also used in Java to define what Threads do, if memory serves (i.e., Runnable) - and we can do this as well in C#:
var thread = new Thread((Action)(() =>
{
// I'm the threads "run" method!
});
thread.Start();
Now, other stuff - enumeration:
public void processEvents(){
for(Event event : eventList)
eventList.execute();
}
C# has the same idea, just called differently:
public void processEvents()
{
// edit: derp, 'event' is a keyword, so I'm
// renaming this, since I won't get into why
// you could also use #event...
foreach(var evt in eventList)
{
evt.Execute();
}
}
EDIT: It looks like your question is about anonymous interface implementations instead of events. You can use the built-in Action delegate type instead of your Event interface.
You can then Action instances using lambda expressions. Your code would look like:
public class TestEvent
{
List<Action> eventList = new List<Action>();
public void addEvent(Action event){
eventList.add(event);
}
public void simulateEvent(){
addEvent(() => {
});
}
public void processEvents(){
for(Action event : eventList)
event();
}
}
You can use the delegate syntax instead of using () => { .. .} i.e.
delegate() { ... } in simulateEvent.
C# doesn't support anonymous interface implementations, so if your interface has multiple methods then you'll have to define a concrete class somewhere. Depending on the usage you could just have this class contain delegate properties which you can supply on creation e.g.
public class Delegates
{
public Action Event { get; set; }
public Func<string> GetValue { get; set; }
}
You can then create it like:
var anon = new Delegates
{
Event = () => { ... },
GetValue = () => "Value"
}