I know that DisposableObserver has implemented both of Observer and Disposable. Flagged onSubscribe() method as final and provided onStart() instead of it.
But I can't understand what are the differences between this two in action. And when I should use Observer or DisposableObserver?
Could you please tell the benefits or disadvantages of using these as compared to each other?
The normal onSubscribe method of observers can be called as many as you use this same observer. but with DisposableObserver onSubscibe method can be called only once meaning that you are only allowed to use this DisposableObserver once. if you pass a single object of DisposableObserver to two stream it will throw exception and close both of them quickly. this logic has been implemented in onSubscribe() of this class thus you can not override it. but in case you need the onSubscribe() callback you can override onStart() method which is the same.
The usage of this class can be as follows.
As per documentation a DisposableObserver is:
An abstract Observer that allows asynchronous cancellation by implementing Disposable.
in other words it means that you can use disposable behaviors inside your observer methods. like calling dispose() in onNext().
Observable.just(1, 2, 3, 4, 5)
.map {
"$it"
}
.subscribe(object : DisposableObserver<String>(){
override fun onComplete() {
}
override fun onNext(t: String) {
println("first item only= $t")
//we can dispose this stream right in the observer methods
dispose()
}
override fun onError(e: Throwable) {
}
})
One may even combine DisposableObserver with subscribeWith() to get almost the same behavior as normal observers.
val disposableObserver = object : DisposableObserver<String>() {
override fun onComplete() {
}
override fun onNext(t: String) {
println("first item only= $t")
//we can dispose this stream right in the observer methods
dispose()
}
override fun onError(e: Throwable) {
}
}
val disposable: Disposable = Observable.just(1, 2, 3, 4, 5)
.map {
"$it"
}
.subscribeWith(disposableObserver)
disposable.dispose()
This and many other classes and operators in RX-Java are there to ease the use of RX and depending on how you want to use the library any of them can be chosen.
Related
The thing is, is there any way (That does not involve reflective black magic), to implicitly override a method, when two known traits are implemented?
Think that we have a class SysImpl that implements two mixins: System and Container:
// Where system acts as the interface for another consumer
trait System {
def isEmpty = false
}
trait Container[A] {
val elements = mutable.Set[A]()
}
// Then, we typically implement:
class SysImpl extends System with Container[Int] {
// We override the default system implementation here
override def isEmpty = elements.isEmpty
}
Just as an example.
Is there any way of implementing either a third trait, or making something to the original, that makes the implementation implicitly override the isEmpty method, in case that System & Container[A] are present?
The first thing that comes to my mind is creating an extension method, but that would be shadowing at its best (Wouldn't it?). I need the method to be overridden properly, as the call is dispatched by a consumer who only sees Systems.
(Example, omitting details)
class AImpl extends System with Container[A]
object Consumer {
def consume(sys: System) = if (sys.isEmpty) { /* Do things */ }
}
// Somewhere...
object Main {
def main() = {
Consumer.consume(new AImpl)
}
}
Just
trait Mix[A] extends Container[A] with System {
override def isEmpty = elements.isEmpty
}
I would like to inject (enrich) behavior and state in a Kotlin class by using an interface. Like class Impl : Observable, where Observable contains state.
In Scala using Traits (does work), looking for a Kotlin solution for this one:
object Test extends App {
val impl = new Impl()
val observer = new Observer()
impl.register(observer)
}
trait Observable {
// How to do this in Kotlin?
val observers = List()
def register(observer: Observer) {
observers.add(observer)
}
}
class Observer
class Parent
class Impl extends Parent with Observable
Attempt in Kotlin (not working):
fun main(args: Array<String>) {
val impl = Impl()
val observer = Observer()
impl.register(observer)
}
interface Observable {
// Error: Kotlin: Property initializers are not allowed in interfaces
val observers = mutableListOf<Observer>()
fun register(observer: Observer) {
observers.add(observer)
}
}
class Observer
open class Parent
class Impl : Parent(), Observable
It results in this error at the interface instance variable line: Kotlin: Property initializers are not allowed in interfaces.
How can I initialize instance variables in Kotlin interfaces?
(Note that in this design, parent classes shouldn't be altered/updated.)
UPDATE: I had an example solution in Java, but that wasn't behaving correctly. "Instance variables" in Java interfaces are automatically static. So I have removed that example.
You can have a placeholder for state in Kotlin interfaces, and let the implementing class provide that state. So the interface can provide the functionality that works against the expected-to-exist state. Such as:
class Observer
interface Observable {
val observers: MutableList<Observer> // not present, but expected
fun register(observer: Observer) {
observers.add(observer)
}
}
open class Parent
class Impl : Parent(), Observable {
override val observers = mutableListOf<Observer>() // used by the interface
}
This is for good reason, there are delicate issues having state coming from more than one item in the class hierarchy and Kotlin is preventing the problems that can arise from such models.
In Java you actually have a static field, not an instance field (unlike Scala code, which does work as you expect):
Every field declaration in the body of an interface is implicitly public, static, and final.
You can achieve the same behavior in Kotlin by putting the field into a companion object.
But what you should actually do is use an abstract class instead of an interface.
Or delegation:
interface Observable {
fun register(observer: Observer)
}
class ObserverList : Observable {
val observers = mutableListOf<Observer>()
override fun register(observer: Observer) {
observers.add(observer)
}
}
class Impl : Parent(), Observable by ObserverList()
I want to do something like this:
interface Serializable<FromType, ToType> {
fun serialize(): ToType
companion object {
abstract fun deserialize(serialized: ToType): FromType
}
}
or even this would work for me:
interface Serializable<ToType> {
fun serialize(): ToType
constructor(serialized: ToType)
}
but neither compiles. Is there a syntax for this, or will I be forced to use make this an interface for a factory? Or is there another answer? 😮 That'd be neat!
Basically, nothing in a companion object can be abstract or open (and thus be overridden), and there's no way to require the implementations' companion objects to have a method or to define/require a constructor in an interface.
A possible solution for you is to separate these two functions into two interfaces:
interface Serializable<ToType> {
fun serialize(): ToType
}
interface Deserializer<FromType, ToType> {
fun deserialize(serialized: ToType): FromType
}
This way, you will be able to implement the first interface in a class and make its companion object implement the other one:
class C: Serializable<String> {
override fun serialize(): String = "..."
companion object : Deserializer<C, String> {
override fun deserialize(serialized: String): C = C()
}
}
Also, there's a severe limitation that only a single generic specialization of a type can be used as a supertype, so this model of serializing through the interface implementation may turn out not scalable enough, not allowing multiple implementations with different ToTypes.
For future uses, it's also possible to give the child class to a function as a receiver parameter:
val encodableClass = EncodableClass("Some Value")
//The encode function is accessed like a member function on an instance
val stringRepresentation = encodableClass.encode()
//The decode function is accessed statically
val decodedClass = EncodableClass.decode(stringRepresentation)
interface Encodable<T> {
fun T.encode(): String
fun decode(stringRepresentation: String): T
}
class EncodableClass(private val someValue: String) {
// This is the remaining awkwardness,
// you have to give the containing class as a Type Parameter
// to its own Companion Object
companion object : Encodable<EncodableClass> {
override fun EncodableClass.encode(): String {
//You can access (private) fields here
return "This is a string representation of the class with value: $someValue"
}
override fun decode(stringRepresentation: String): EncodableClass {
return EncodableClass(stringRepresentation)
}
}
}
//You also have to import the encode function separately:
// import codingProtocol.EncodableClass.Companion.encode
This is the more optimal use case for me. Instead of one function in the instanced object and the other in the companion object like your example, we move both functions to the companion object and extend the instance.
trait UserRepository {
def findByFirstName(firstName: String): Seq[User]
}
trait UserBusinessDelegate extends UserRepository {
abstract override def findByFirstName(firstName: String) = {
super.findByFirstName(firstName)
}
}
class MockUserRepository extends UserRepository {
override def findByFirstName(firstName: String) = {
// whatever
}
}
val userRepository = new MockUserRepository with UserBusinessDelegate
userRepository.findByFirstName("John") // OK
However, if I change UserBusinessDelegate as follows:
trait UserBusinessDelegate {
self: UserRepository =>
override def findByFirstName(firstName: String): Seq[User] = {
self.findByFirstName(firstName) // requires explicit return type, thinks this is a recursive call
}
}
val userRepository = new MockUserRepository with UserBusinessDelegate
userRepository.findByFirstName("John") // StackOverflow!!!
I understand stackable pattern and hence how the first case works. My question is why the 2nd doesn't.
In the second snippet you have a recursive call without an exit condition:
override def findByFirstName(firstName: String): Seq[User] = {
self.findByFirstName(firstName)
}
This will always call findByFirstName from UserBusinessDelegate (because you're using self, which basically says that this object will have this kind of behaviour at runtime, not that it's parent will have it and therefore we should call parent's method) creating a new stack frame with each call -> stack overflow.
In the second snippet UserBusinessDelegate's findByFirstName will be called and then you call MockUserRepository's method from it using super -> no recursion -> no stack overflow. You can check Scala's stackable trait pattern for more info.
#Edit: to make it more clear, in the snippet that throws a SO exception the findByFirstName method from MockUserRepository won't be called because you are overriding it in UserBusinessDelegate therefore the anonymous class created with new MockUserRepository with UserBusinessDelegate will only contain the overriden method and that's why the SO, is that clear?
Why would you assume that the method from MockUserRepository would get invoked?
#Edit2: the code doesn't compile without override because self: UserRepository => tells the compiler that a method with such a signature will already be there at runtime and you cannot have 2 methods with the same signature. The first example works only because it's a stackable trait, such traits are dynamically bound and can modify the behaviour but have to call super at some point (which normally isn't allowed without the abstract override modifier, I really recommend going through the link I posted about stackable pattern).
Maybe someone else knows a way, from what I know there's no way to call the mock method unless you change the method name in UserBusinessDelegate and drop the override, then you can call self.findByFirstName and it will call the method from MockUserRepository.
I have a Actor that goes like this (assume that the receive method is overridden somewhere else):
class MyClass extends Actor {
def method1() = { ... }
def method2() = { ... }
def method3() = {
this.synchronized {
....
....
}
}
}
What happens if I have a final field defined in my Actor as:
private val lockType = new AnyRef
I then can use this lock to synchronize my method3? What would be the difference? My understanding is that using this reference to lock on a method would make that reference unavailable until the lock is released.
In the above case, I use a lock that can function independently of the this reference and lock only when some action on method3 is made, while the this reference is still available for the other threads?
There's no need for synchronization inside of an actor. The actor will only ever process a single message at a time.