I'am coming from java and I have little difficulties to learn the patterns.
I have the first protocol
protocol Interval
{
}
And the second:
protocol Event
{
associatedtype IntervalType: Interval
var interval: IntervalType
func doSomething(param: IntervalType )
}
How can i make an array with the type Event?
I took a look at the type-erase and the solution that it gives it to create a struct like this one:
public struct AnyEvent<intervalType: Interval>: Event {...}
But it only gives me the possibility to create an array with any event type and only one type of Interval, I want to make an array with any kind of Events that could contain any kind of Intervals, something like: [AnyEvent] or [AnyEvent<Interval>]
I also want to ask if there is a possibility to make Event extend Equatable and define it in the type-erase.
Edit:
Hoping someone is good at both swift and java, and can provide a translated pattern for this:
A simple common interval interface:
interface ReadableInterval {...}
Two types that confirms the readable interval:
class Interval implements ReadableInterval {...}
class MutableInterval implements: ReadableInterval {...}
A common events interface:
interface ReadablEvent
{
ReadableInterval getInterval();
}
Two types of events that could have different intervals, with the specialized return type of the methods:
class Event implements: ReadablEvent
{
private Interval interval = new Interval();
Interval getInterval()
{
return interval;
}
}
class MutableEvent implements: ReadablEvent
{
private MutableInterval interval = new MutableInterval();
MutableInterval getInterval()
{
return interval;
}
}
and then i want to have a list or array with the both Event and MutableEvent like:
ArrayList<ReadableEvent>
or
ReadableEvent[]
As you know in Swift you cannot declare an array of a protocols with an associated type (please read this for more details)
However you can declare a new protocol like this
protocol AnyEvent {
var interval: Interval { get }
func doSomething(param: Interval )
}
Your 3 protocols should now look like this
protocol Interval {
}
protocol AnyEvent {
var interval: Interval { get }
func doSomething(param: Interval )
}
protocol Event: AnyEvent {
associatedtype IntervalType: Interval
var interval: IntervalType { get }
func doSomething(param: IntervalType )
}
Usage
To use these protocols we need some structs (or classes) that conform to them
struct TimeInterval: Interval { }
struct TapEvent: AnyEvent {
var interval: Interval = TimeInterval()
func doSomething(param: Interval) {
print("It's a tap")
}
}
struct GestureEvent: AnyEvent {
var interval: Interval = TimeInterval()
func doSomething(param: Interval) {
print("It's a gesture")
}
}
Now we can
var events = [AnyEvent]()
events.append(TapEvent())
events.append(GestureEvent())
for event in events {
event.doSomething(TimeInterval())
}
It's a tap
It's a gesture
I also want to ask if there is a possibility to make Event extend Equatable and define it in the type-erase
Yes you just need to add the declaration
protocol Event: AnyEvent, Equatable {
associatedtype IntervalType: Interval
var interval: IntervalType { get }
func doSomething(param: IntervalType )
}
Now you are forcing every struct o class conform to Event to be Equatable.
Related
I try to write a transformation function which is used with compose() in order to reduce boilerplate code. It's pretty simple like this:
fun <R> withSchedulers(): ObservableTransformer<R, R> {
return ObservableTransformer {
it.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
}
So everytime I want to subscribe to anything on ioThread and listen the result on mainThread, it's just few lines of code:
Observable.just(1)
.compose(MyUtilClass.withSchedulers())
.subscribe()
But there isn't Observable only, but we also have Single, Completable, Maybe and Flowable. So every time I want to combine them with my withSchedulers() function, I have to transform it into the new type (which I don't expect).
For example,
Completable.fromAction {
Log.d("nhp", "hello world")
}//.compose(MyUtilClass.withSchedulers()) <-- This is not compiled
.toObservable() <--- I have to transform it into Observable
.compose(MyUtilClass.withSchedulers())
.subscribe()
So my question is, is there any way to write the above function to use with compose() for any kind of Observable (Single, Completable,...) ? Or we have to write different functions which use ObservableTransformer, SingleTransformer, ....?
I created a helper method using reified type :
inline fun <reified T> withSchedulers(): T {
when (T::class) {
ObservableTransformer::class -> return ObservableTransformer<Unit, Unit> {
it.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
} as T
SingleTransformer::class -> return SingleTransformer<Unit, Unit> {
it.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
} as T
CompletableTransformer::class -> return CompletableTransformer {
it.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
} as T
}
throw IllegalArgumentException("not a valid Transformer type")
}
Examples :
Observable.just("1", "2")
.compose(withSchedulers<ObservableTransformer<String, String>>())
.subscribe(System.out::println)
Single.just(3)
.compose(withSchedulers<SingleTransformer<Int, Int>>())
.subscribe(Consumer { println(it) })
Completable.defer { Completable.complete() }
.compose(withSchedulers<CompletableTransformer>())
.subscribe { println("completed") }
Output :
1
2
3
completed
Probably other ways of doing this, but this came to mind.
As I converted this method in Java:
private void enqueueDownloads() {
final List<Request> requests = Data.getFetchRequestWithGroupId(GROUP_ID);
fetch.enqueue(requests, updatedRequests -> {
}, error -> Timber.d("DownloadListActivity Error: %1$s", error.toString()));
}
It led to this method which has a lot of errors:
private fun enqueueDownloads() {
val requests = Data.getFetchRequestWithGroupId(GROUP_ID)
fetch.enqueue(requests, { updatedRequests ->
}, { error -> Timber.d("DownloadListActivity Error: %1\$s", error.toString()) })
}
This method in Kotlin has a lot of errors at the method fetch.enqueue where the value updatedRequestsand error it says Cannot infer a type for this parameter.
So I hit hover on the method and hit Ctrl+B and the method declaration in the library is:
fun enqueue(requests: List<Request>, func: Func<List<Request>>? = null, func2: Func<Error>? = null): Fetch
/** Pause a queued or downloading download.
* #param ids ids of downloads to be paused.
* #param func Callback the paused downloads will be returned on. Note. Only downloads that
* were paused will be returned in the result list.
* #param func2 Callback that is called when attempting to pause downloads fail. An error is returned.
* #throws FetchException if this instance of Fetch has been closed.
* #return Instance
* */
The problem has something to do with CallBack based on the method documentation but I can not get it to work! How can I make it fully Kotlin and call it in Kotlin?.
The library is Fetch2 and written in Kotlin. Also I can not see whole code for the methods in the library.
TLDR: the shortes syntax in your specific case is:
fetch.enqueue(requests, Func { updatedRequests ->
}, Func { error -> Timber.d("DownloadListActivity Error: %1\$s", error) })
The issue here is that you are calling function written in Kotlin. You can't use the short lambda syntax here, since Kotlin will not turn lambdas automatically into the right interface in that case.
"Kotlin has proper function types, automatic conversion of functions into implementations of Kotlin interfaces is unnecessary and therefore unsupported." (source)
Usually to implement (Kotlin) interfaces anonymously in Kotlin you'll have to use the full-blown object Syntax:
interface KFunc<T> { fun call(result: T) }
val func = object : KFunc<String> {
override fun call(result: String) {
println(result)
}
}
However Func is an interface defined in Java so Kotlin offers an automatic conversion utility and you can write
val func: Func<String> = Func {
result -> println(result)
}
This is because there is an automatically generated method for every Java interface. In this case below code is generated
fun <T> Func(function: (result: T) -> Unit): Func<T> {
return object : Func<T> {
override fun call(result: T) {
function(result) // call the function
}
}
}
If the method that takes the Func was also written in Java that's where you can even leave out the Func {} part. E.g. given
public class JavaClass {
public static void doWithFunc(Func<String> func) {
func.call("Hello");
}
}
you could write
JavaClass.doWithFunc { result -> println(result) }
However given
object KotlinClass {
#JvmStatic
fun doWithFunc(func: Func<String>) {
func.call("Hello")
}
}
you must write at least
KotlinClass.doWithFunc(Func { result -> println(result) })
On the other hand from Java(8+) you can use lambdas in both cases
JavaClass.doWithFunc(string -> System.out.println(string));
KotlinClass.doWithFunc(string -> System.out.println(string));
It's a little confusing. At the moment, APIs written in Kotlin that are meant for Kotlin consumption shouldn't use functional interfaces but actual function parameters, i.e. for the enqueue function which is
fun enqueue(requests: List<Request>, func: Func<List<Request>>? = null, func2: Func<Error>? = null): Fetch
they would ideally also offer
fun enqueue(requests: List<Request>, func: ((List<Request>) -> Unit)? = null, func2: ((Error) -> Unit)? = null): Fetch
which would allow you to call it like expected in Kotlin
fixedFetch.enqueue(requests, { println(it) }, { Timber.w(it) })
The downside is that this gives a fairly odd looking method for Java users of the library since Kotlin uses it's Function1 interface to represent function parameters. You'll also have to return Unit.INSTANCE since that's actually a type in Kotlin.
Fetch enqueue(List<? extends Request>, Function1<? super List<? extends Request>, Unit>, Function1<? super Error, Unit>)
I am trying to implement a content-based router in my Akka actor system and according to this document the ConsistentHashingRouter is the way to go. After reading through its official docs, I still find myself confused as to how to use this built-in hashing router. I think that’s because the router itself is hash/key-based, and the example the Akka doc author chose to use was a scenario involving key-value based caches…so I can’t tell which keys are used by the cache and which ones are used by the router!
Let’s take a simple example. Say we have the following messages:
interface Notification {
// Doesn’t matter what’s here.
}
// Will eventually be emailed to someone.
class EmailNotification implements Notification {
// Doesn’t matter what’s here.
}
// Will eventually be sent to some XMPP client and on to a chatroom somewhere.
class ChatOpsNotifications implements Notification {
// Doesn’t matter what’s here.
}
etc. In theory we might have 20 Notification impls. I’d like to be able to send a Notification to an actor/router at runtime and have that router route it to the correct NotificationPubisher:
interface NotificationPublisher<NOTIFICATION implements Notification> {
void send(NOTIFICATION notification)
}
class EmailNotificationPublisher extends UntypedActor implements NotificationPubisher<EmailNotification> {
#Override
void onReceive(Object message) {
if(message instanceof EmailNotification) {
send(message as EmailNotification)
}
}
#Override
void send(EmailNotification notification) {
// Use Java Mail, etc.
}
}
class ChatOpsNotificationPublisher extends UntypedActor implements NotificationPubisher<ChatOpsNotification> {
#Override
void onReceive(Object message) {
if(message instanceof ChatOpsNotification) {
send(message as ChatOpsNotification)
}
}
#Override
void send(ChatOpsNotification notification) {
// Use XMPP/Jabber client, etc.
}
}
Now I could do this routing myself, manually:
class ReinventingTheWheelRouter extends UntypedActor {
// Inject these via constructor
ActorRef emailNotificationPublisher
ActorRef chatOpsNotificationPublisher
// ...20 more publishers, etc.
#Override
void onReceive(Object message) {
ActorRef publisher
if(message instanceof EmailNotification) {
publisher = emailNotificationPublisher
} else if(message instanceof ChatOpsNotification) {
publisher = chatOpsNotificationPublisher
} else if(...) { ... } // 20 more publishers, etc.
publisher.tell(message, self)
}
}
Or I could use the Akka-Camel module to defined a Camel-based router and send Notifications off to the Camel router, but it seems that Akka aready has this built-in solution, so why not use it? I just cant figure out how to translate the Cache example from those Akka docs to my Notification example here. What’s the purpose of the “key” in the ConsistentHashingRouter? What would the code look like to make this work?
Of course I would appreciate any answer that helps me solve this, but would greatly prefer Java-based code snippets if at all possible. Scala looks like hieroglyphics to me.
I agree that a Custom Router is more appropriate than ConsistentHashingRouter. After reading the docs on custom routers, it seems I would:
Create a GroupBase impl and send messages to it directly (notificationGroup.tell(notification, self)); then
The GroupBase impl, say, NotificationGroup would provide a Router instance that was injected with my custom RoutingLogic impl
When NotificationGroup receives a message, it executes my custom RoutingLogic#select method which determines which Routee (I presume some kind of an actor?) to send the message to
If this is correct (and please correct me if I’m wrong), then the routing selection magic happens here:
class MessageBasedRoutingLogic implements RoutingLogic {
#Override
Routee select(Object message, IndexedSeq<Routee> candidates) {
// How can I query the Routee interface and deterine whether the message at-hand is in fact
// appropriate to be routed to the candidate?
//
// For instance I'd like to say "If message is an instance of
// an EmailNotification, send it to EmailNotificationPublisher."
//
// How do I do this here?!?
if(message instanceof EmailNotification) {
// Need to find the candidate/Routee that is
// the EmailNotificationPublisher, but how?!?
}
}
}
But as you can see I have a few mental implementation hurdles to cross. The Routee interface doesn’t really give me anything I can intelligently use to decide whether a particular Routee (candidate) is correct for the message at hand.
So I ask: (1) How can I map messages to Routees (effectively performing the route selection/logic)? (2) How do I add my publishers as routees in the first place? And (3) Do my NotificationPublisher impls still need to extend UntypedActor or should they now implement Routee?
Here is a simple little A/B router in Scala. I hope this helps even though you wanted a Java based answer. First the routing logic:
class ABRoutingLogic(a:ActorRef, b:ActorRef) extends RoutingLogic{
val aRoutee = ActorRefRoutee(a)
val bRoutee = ActorRefRoutee(b)
def select(msg:Any, routees:immutable.IndexedSeq[Routee]):Routee = {
msg match{
case "A" => aRoutee
case _ => bRoutee
}
}
}
The key here is that I am passing in my a and b actor refs in the constructor and then those are the ones I am routing to in the select method. Then, a Group for this logic:
case class ABRoutingGroup(a:ActorRef, b:ActorRef) extends Group {
val paths = List(a.path.toString, b.path.toString)
override def createRouter(system: ActorSystem): Router =
new Router(new ABRoutingLogic(a, b))
val routerDispatcher: String = Dispatchers.DefaultDispatcherId
}
Same thing here, I am making the actors I want to route to available via the constructor. Now a simple actor class to act as a and b:
class PrintingActor(letter:String) extends Actor{
def receive = {
case msg => println(s"I am $letter and I received letter $msg")
}
}
I will create two instances of this, each with a different letter assignment so we can verify that the right ones are getting the right messages per the routing logic. Lastly, some test code:
object RoutingTest extends App{
val system = ActorSystem()
val a = system.actorOf(Props(classOf[PrintingActor], "A"))
val b = system.actorOf(Props(classOf[PrintingActor], "B"))
val router = system.actorOf(Props.empty.withRouter(ABRoutingGroup(a,b)))
router ! "A"
router ! "B"
}
If you ran this, you would see:
I am A and I received letter A
I am B and I received letter B
It's a very simple example, but one that shows one way to do what you want to do. I hope you can bridge this code into Java and use it to solve your problem.
I have a test application that spawns a number of SocketConversations with a server. In the old days, I would have added an interface called ClosedWhenDone or something that defined a close method and pass an instance in that would notify the calling class that the SocketConversation is complete.
I'm new to java 8 and want to teach myself lambda functions. I have looked at these: http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html, http://viralpatel.net/blogs/lambda-expressions-java-tutorial/, http://java.dzone.com/articles/why-we-need-lambda-expressions, http://java.dzone.com/articles/why-we-need-lambda-expressions-0, and http://java.dzone.com/articles/why-we-need-lambda-expressions.
So, based on my research, I added a parameter to my constructor:
private Predicate<SocketConversation> closePredicate;
private long delay;
private boolean done;
private int index;
public SocketConversation(URI uri, int idx, String line, long delay, Predicate<SocketConversation> predicate) {
index = idx;
socket = new AirSocketClient(uri, this);
closePredicate = predicate;
...
}
Then when my conversation is over, I do the following:
socket.close();
closePredicate.close(this);
The close here, though, generates an error:
The method close(SocketConversation) is undefined for the type Predicate<SocketConversation>
What am I missing?
It sounds like what you want is a callback that lets the caller know that the conversation is complete, by calling a bit of code that the caller has specified. This sounds like a perfect use of lambdas. In the "old" days (prior to Java 8) you'd specify some interface and the caller would pass in an instance of an anonymous inner class. This can easily be done with a lambda instead.
You could define your own interface, but you don't need to in this case because most of the simple interfaces have already been defined. In this case the callback is passed an instance of a SocketConversation and returns nothing. The functional interface for this is a Consumer, which is already defined in java.util.function package. It's generic, so you want a Consumer<SocketConversation>. Your class would look something like this:
private Consumer<SocketConversation> callback;
public SocketConversation(URI uri, int idx, String line, long delay, Consumer<SocketConversation> callback) {
this.callback = callback;
...
}
and later on, when the conversation is closed, you'd do this:
socket.close();
callback.accept(this);
Callers could pass a lambda expression as the callback like this:
SocketConversation conv = new SocketConversation(uri, idx, line, delay,
sc -> System.out.println("conversation " + sc + " is done"));
i currently have a Java Observer/Observable setup in which i switch on some field within the Object parameter of Observer.update (e.g. event id) to determine how to handle an Observable notification.
this creates verbose code like:
public void update (Observable o, Object arg) {
if (arg instanceof Event) {
switch (((Event)arg).getID()) {
case EVENT_TYPE_A:
// do stuff...
break;
case EVENT_TYPE_B:
// do stuff...
break;
case EVENT_TYPE_C:
// do stuff...
break;
}
}
}
coming from an ActionScript background, this feels unnecessarily verbose to me...instead of passing an instance of an Observer, i'd prefer to pass a callback method to be called directly by the Observable (more specifically, by a subclass). however, i'm not clear how to determine the object on which the method should be invoked (the class instance that 'owns' the method).
i could pass a reference to the instance enclosing the method, but this smells like bad OOP.
am i barking up the wrong tree? or is there a clean way to achieve this?
This may be a little far out in left-field, but since Java 5 and up have generics, both the traditional observer and listener patterns seem a little bit dated. That is to say, types are the lingua-fraca of java these days. Events with integer IDs exist principally because switch statements against constants are extremely efficient - at the expense of readability and often requiring casts to do anything useful (you may know that if the ID = 23, the Object must be a MouseEvent, but it is nicer and safer if you let the compiler and runtime type information take care of this for you). On a modern machine in a modern JVM, the efficiency may not be worth it.
So, if you are not married to IDs and the traditional observer pattern, you might consider something like this:
public abstract class Observer<T> {
private final Class<T> type;
protected Observer(Class<T> type) {
this.type = type;
}
//implement this method; if it returns false, the event (object)
//is "consumed" and no other observers should be called
public abstract boolean onEvent(T instance);
protected final boolean matches(Object obj) {
return type.isInstance(obj);
}
Boolean maybeDispatch(Object o) {
if (matches(o)) {
return onEvent(type.cast(o));
}
return null;
}
}
This gets us (literally) a generic Observer of events; we switch on the type of the object passed in like this:
public class Bus {
private final List<Observer<?>> observers = new ArrayList<Observer<?>>();
public void registerObserver(Observer<?> observer) {
observers.add(observer);
}
public <T> void onEvent(T t) {
Boolean keepGoing;
for (Observer<?> obs : observers) {
keepGoing = obs.maybeDispatch(t);
if (keepGoing != null && !keepGoing.booleanValue()) {
break;
}
}
}
}
The resulting code is (marginally) less efficient, but writing a subclass of such an "observer" is infinitely more readable. It does not look much like the traditional observer pattern, but is functionally equivalent.
If you still need an additional "event" parameter, you can just do similar logic to parameterize on two types.
A cleaner implementation would involve removing the logic of whether the event can be handled by the observer/observable, to the actual observer/observable itself. It appears as if ActionScript has left you with a funny idea about the Observer pattern. Observe (no-pun-intended):
public interface Observer{
public void update( Event arg );
}
public class Event{
public int ID;
}
public Button implements Observer{
public void update ( Event arg ){
switch (arg.ID){
case 1: //Buttonsy handle events of type 1
//do something useful;
break;
default:
System.out.println("Buttons don't handle events of ID: " + arg.ID);
break;
}
}
}
public ProgressBar implements Observer{
public void update ( Event arg ){
switch (arg.ID){
case 2: //ProgressBars handle events of type 2 and 3
//do something useful;
break;
case 3:
//do something else useful;
break;
default:
System.out.println("Progress bars don't handle events of ID: " + arg.ID);
break;
}
}
}
public class Subject{
private ArrayList<Observer> allUIControls;
public registerControl( Observer control ){
allUIControls.add( control );
}
public void updateControls ( Event arg ) {
foreach ( Observer control in allUIControls ){
//pass the event to each UI control, and let the EVENT decide if it can understand the Event.ID
//its not the job of Subject to decide if the Observer is fit to handle the event. THIS IS NOT THE OBSERVER pattern.
control.update( arg );
}
}
}