I have this arraylist of GameObjects. I loop through the arraylist, and if the type of the object is door (one of the GameObject's child classes), and if some other conditions match up, i want to call a function from the door class thats only in that class. Is this possible? I'm using Kotlin, but if you only know java i could probably port it.
You can use is, as? or with operators combined with smart casts for that.
In java you can code as below:
for (GameObject gameObject: GameObjects) {
if(gameObject instanceof Door ) { // you can add your another condition in this if itself
// your implementation for the door object will come here
}
}
You can use like this:
//Kotlin 1.1
interface GameObject {
fun age():Int
}
class GameObjectDoor(var age: Int) : GameObject{
override fun age():Int = age;
override fun toString():String = "{age=$age}";
}
fun main(args: Array<String>) {
val gameObjects:Array<GameObject> = arrayOf(
GameObjectDoor(1),
GameObjectDoor(2),
GameObjectDoor(3));
for (item: GameObject in gameObjects) {
when (item) {
is GameObjectDoor -> {
var door = item as GameObjectDoor
println(door)
//do thomething with door
}
//is SomeOtherClass -> {do something}
}
}
}
Related
Is there a way to register a codec for multiple classes? Basically, all my classes should just be serialized using a Jackson object mapper. But it seems like I have to create a custom codec for each class (even though I can abstract it a little bit using generics).
A small code example:
Codec:
class JacksonCodec<T>(private val mapper: ObjectMapper, private val clazz: Class<T>) : MessageCodec<T, T> {
override fun encodeToWire(buffer: Buffer, s: T) {
buffer.appendBytes(mapper.writeValueAsBytes(s))
}
override fun decodeFromWire(pos: Int, buffer: Buffer): T {
val length = buffer.getInt(pos)
val bytes = buffer.getBytes(pos + 4, pos + 4 + length)
return mapper.readValue(bytes, clazz)
}
...
}
register codec for each class I want to serialize:
vertx.eventBus()
.registerDefaultCodec(A::class.java, JacksonCodec(DatabindCodec.mapper(), A::class.java))
vertx.eventBus()
vertx.eventBus()
.registerDefaultCodec(B::class.java, JacksonCodec(DatabindCodec.mapper(), B::class.java))
vertx.eventBus()
The code examples are kotlin but same applies for Java.
As far as I can tell looking at the code, there is no way, as the class needs to be the exact match:
https://github.com/eclipse-vertx/vert.x/blob/master/src/main/java/io/vertx/core/eventbus/impl/CodecManager.java#L99
It is possible, with some limitations and quirks. I would not recommend doing it.
Let's start with the limitations:
It can not be used in clustered mode
You have to declare the codec name every time you send something over the eventbus.
If you create a generic codec that encodes classes with Jackson and every time you send something over the eventbus you make sure to add it using codecName in the deliveryOptions, you can register it only once and use it for all of your classes.
Full example:
fun main() {
val vertx = Vertx.vertx()
vertx.eventBus().registerCodec(GenericCodec())
vertx.eventBus().consumer<Foo>("test-address") {
println(it.body())
it.reply(Bar(), genericDeliveryOptions)
}
vertx.eventBus().request<String>("test-address", Foo(), genericDeliveryOptions) {
println(it.result().body())
}
vertx.close()
}
data class Foo(
val foo: String = "foo",
)
data class Bar(
val bar: String = "bar",
)
class GenericCodec : MessageCodec<Any, Any> {
companion object {
const val NAME = "generic"
}
private val mapper: ObjectMapper = ObjectMapper()
override fun encodeToWire(buffer: Buffer, s: Any) {
buffer.appendBytes(mapper.writeValueAsBytes(s))
}
override fun decodeFromWire(pos: Int, buffer: Buffer): Any {
throw RuntimeException("should never get here, unless using clustered mode")
}
override fun transform(s: Any): Any {
return s
}
override fun name(): String {
return NAME
}
override fun systemCodecID(): Byte {
return -1
}
}
val genericDeliveryOptions = deliveryOptionsOf(codecName = GenericCodec.NAME)
I got a tricky issue concerning collection filtering in kotlin...
I got a base class that manages a list of items and I want to be able to filter the list with a keyword so I extended the class with Filterable methods.
What I want to do is to be able to extend multiple classes with this 'base class' so the filter mecanism is the same for all classes.
These classes don't have the same properties... In one, the filtering must occur depending if the keyword is found in the 'name' while in another class the filtering is done on the 'comment' property.
Here some code:
data class ProductInfo(): {
var _name: String
var name: String
get() = _name
set(value) { _name = value }
}
abstract class BaseFirestoreAdapter<T : BaseFirestoreAdapter.DataInterface, VH : RecyclerView.ViewHolder> : RecyclerView.Adapter<VH>(), Filterable
{
var sourceList: MutableList<ProductInfo> = ArrayList()
...
override fun performFiltering(keyword: CharSequence): FilterResults {
val keywordRegex = keyword.toString().toRegex(setOf(RegexOption.IGNORE_CASE, RegexOption.LITERAL))
filteredList = sourceList.filter {
keywordRegex.containsMatchIn(Normalizer.normalize(it.name, Normalizer.Form.NFD).replace("[^\\p{ASCII}]".toRegex(RegexOption.IGNORE_CASE), ""))
}
results.values = filteredList.sortedWith(orderComparator)
results.count = filteredList.size
}
...
}
I developped the 'base class' so it works with the first class mentionned above (filtering is done with the 'it.name') and it works but now that I'm trying to make it generic (T) to use it with the second class (comments), I can't find a way to do it...
I thought I could pass a class related predicate defining how to match the items during the filtering but since the keyword is only known in the performFiltering method, I can't create properly the predicate outside of this method...
I'm kinda out of ideas now! lol
Any of you have an idea?
UPDATE: Following #Tenfour04's suggestion, I tried adapting it to my code which passes filtering predicates via a method instead of using the constructor but it does not compile unless I replace "ActivyInfo::comments" with something like "ActivyInfo::comments.name" but then the
value I get for "searchedProperty(it)" in debug is "name" which is not the comment value.
Here is the code:
CommentAdapter:
override fun getFilter(): Filter {
super.setFilter(
{ it.state != ProductState.HIDDEN },
{ ActivyInfo::comments },
compareBy<ProductInfo> { it.state }.thenBy(String.CASE_INSENSITIVE_ORDER) { it.name })
return super.getFilter()
}
BaseAdapter:
lateinit var defaultFilterPredicate : (T) -> Boolean
lateinit var searchedProperty : (T) -> CharSequence
lateinit var orderComparator : Comparator<T>
fun setFilter(defaultPredicate: (T) -> Boolean, property: (T) -> CharSequence, comparator: Comparator<T> ) {
defaultFilterPredicate = defaultPredicate
searchedProperty = property
orderComparator = comparator
}
override fun performFiltering(constraint: CharSequence): FilterResults {
...
filteredList = sourceList.filter {
constraintRegex.containsMatchIn(Normalizer.normalize(searchedProperty(it), Normalizer.Form.NFD).replace("[^\\p{ASCII}]".toRegex(RegexOption.IGNORE_CASE), ""))
}
...
}
You can pass into the constructor a parameter that specifies the property as a function.
abstract class BaseFirestoreAdapter<T : BaseFirestoreAdapter.DataInterface, VH : RecyclerView.ViewHolder>(val filteredProperty: (T) -> CharSequence) : RecyclerView.Adapter<VH>(), Filterable
{
var sourceList: MutableList<T> = ArrayList()
// ...
override fun performFiltering(keyword: CharSequence): FilterResults {
val keywordRegex = keyword.toString().toRegex(setOf(RegexOption.IGNORE_CASE, RegexOption.LITERAL))
filteredList = sourceList.filter {
keywordRegex.containsMatchIn(Normalizer.normalize(filteredProperty(it), Normalizer.Form.NFD).replace("[^\\p{ASCII}]".toRegex(RegexOption.IGNORE_CASE), ""))
}
results.values = filteredList.sortedWith(orderComparator)
results.count = filteredList.size
}
...
}
The changes I made to yours were adding the constructor parameter filteredProperty, Changing the sourceList type to T, and replacing it.name with filteredProperty(it).
So subclasses will have to call this super-constructor, passing the property in like this:
data class SomeData(val comments: String)
class SomeDataAdapter: BaseFirestoreAdapter<SomeData>(SomeData::comments) {
//...
}
Or if you want to keep it generic:
class SomeDataAdapter(filteredProperty: (T) -> CharSequence): BaseFirestoreAdapter<SomeData>(filteredProperty) //...
I'm currently designing database for a mobile application. Recently I found very useful function to access database in background:
private val IO_EXECUTOR = Executors.newSingleThreadExecutor()
fun ioThread(f : () -> Unit) {
IO_EXECUTOR.execute(f)
}
Besides that I figured out that don't need synchronization code as the database will be accessed only in one thread (i.e the thread used by SingleThreadExecutor).
The only issue is that the following methods have to be restricted to be invoked only through ioThread function (or using IO_EXECUTOR).
abstract class MyDatabase : RoomDatabase() {
companion object {
fun init(context: Context) { ... }
fun getInstance() { ... }
}
Is it possible to achieve this in Kotlin/Java?
UPDATE: for now I have this implementation but think there should be better ones
// App.kt file
private val IO_EXECUTOR = Executors.newSingleThreadExecutor()
private var IO_THREAD_ID: Long = -1L
private fun getIOThreadId(): Long {
if (IO_THREAD_ID == -1L)
IO_THREAD_ID = IO_EXECUTOR.submit(Callable<Long> { Thread.currentThread().id }).get()
return IO_THREAD_ID
}
fun notInIOThread() = Thread.currentThread().id != getIOThreadId()
fun ioThread(f : () -> Unit) {
IO_EXECUTOR.execute(f)
}
and then use notInIOThread() in init() and getInstance() functions
If you absolutely need to make sure that the code is running on the correct thread, you could make use of a custom thread and then checking Thread.currentThread() for the interface.
private interface MarkedIOThread // Marker interface
private val IO_EXECUTOR = Executors.newSingleThreadExecutor { r ->
return object : Thread(r), MarkedIOThread
}
fun notInIOThread(): Boolean = Thread.currentThread() !is MarkedIOThread
Yes, you can use android annotations`s Worker Thread annotation.
When you annotate a method or class with #WorkerThread, android will give you lint errors if you call it from the UI thread.
You can read more about the #WorkerThread here: https://developer.android.com/reference/android/support/annotation/WorkerThread
And more about android annotations here: https://developer.android.com/studio/write/annotations
I would suggest that you should check room library: https://developer.android.com/topic/libraries/architecture/room
It is very powerful, if you don't have any specific reason to create a database library, room is your best bet.
I assume you want the functions to be called only inside ioThread code block, otherwise there'd be a type error. First make them member functions of a class with user-code-inaccessible constructor so others cannot call it directly:
class MyDslClass internal constructor() {
fun init(context: Context) { ... }
fun getInstance() { ... }
}
And ioThread should be:
fun ioThread(f : MyDslClass.() -> Unit) {
val dsl = MyDslClass()
IO_EXECUTOR.execute { dsl.f() }
}
Then you can restrict calls to those functions only inside ioThread block.
fun main(args: Array<String>) {
ioThread {
getInstance() // Ok
}
// cannot call `getInstance` since I cannot construct a `MyDslClass`
}
What is kotlin equivalent of this java class?
public class StatefulActor extends AbstractActor<StatefulActor.State> implements Some
{
public static class State
{
String lastMessage;
}
}
I tried:
class HelloActor: AbstractActor<HelloActor.State>(), Hello
{
inner class State {
var lastMessage: String? = null
}
but results in Cloud.orbit.exception.UncheckedException: Don't know how to handle state
What is kotlin equivalent of this java class?
Your Kotlin and Java code differs in two ways, the relationship of the State to StatefulActor and the ability of State to allow subclassing.
For State what you want is a Nested class not an Inner class in Kotlin terms. The former corresponds to static modifier in Java whereas the latter is like an inner class without the static modifier.
So for equivalence with the Java code you gave, you should drop the inner keyword.
Cloud.orbit.exception.UncheckedException: Don't know how to handle state
As for your Orbit problem you can try the following. This will also explain why subclassing is an issue:
// compile and run with cloud.orbit:orbit-runtime:1.2.0
import cloud.orbit.actors.runtime.AbstractActor
import cloud.orbit.actors.Actor
import cloud.orbit.actors.Stage
import cloud.orbit.concurrent.Task
class HelloActor: AbstractActor<HelloActor.ActorState>(), Hello
{
override fun sayHello(greeting: String): Task<String> {
val lastMessage = state().lastMessage
state().lastMessage = greeting
return Task.fromValue(lastMessage)
}
class ActorState {
var lastMessage: String? = null
}
}
interface Hello : Actor {
fun sayHello(greeting: String): Task<String>
}
fun main(args : Array<String>) {
val stage = Stage.Builder().clusterName("orbit-helloworld-cluster").build()
stage.start().join()
stage.bind()
val helloActor = Actor.getReference(Hello::class.java, "0");
var response = helloActor
.sayHello("Welcome to orbit 1").join()
println(response) // should print null
response = helloActor
.sayHello("Welcome to orbit 2").join()
println(response) // should print "Welcome to orbit 1"
stage.stop().join()
}
Notice that the Actor's nested class is called ActorState and not State as in your question. When I named the Actor's state class State I got a similar error:
cloud.orbit.exception.UncheckedException: Don't know how to handle state: HelloActor$State...
Caused by: cloud.orbit.exception.UncheckedException: cloud.orbit.exception.UncheckedException: Don't know how to handle state: HelloActor$State
Caused by: cloud.orbit.exception.UncheckedException: Don't know how to handle state: HelloActor$State
Caused by: cloud.orbit.exception.UncheckedException: java.lang.ClassNotFoundException: HelloActor$ActorState
But when I used the nested class name HelloActor.ActorState instead it works.
This is because by default all classes in Kotlin are closed (i.e. final in Java terms).
By default, all classes in Kotlin are final, which corresponds to Effective Java, Item 17: Design and document for inheritance or else prohibit it.
While in orbit 1.2.0 the code (if you do not use the special name ActorState) tries to subclass your State class and then instantiate it. This will not work if you go with the closed Kotlin default extensibility.
If you wish to use your own name for the Actor's state class you must declare it as open. e.g.
class HelloActor: AbstractActor<HelloActor.State>(), Hello
{
override fun sayHello(greeting: String): Task<String> {
val lastMessage = state().lastMessage
state().lastMessage = greeting
return Task.fromValue(lastMessage)
}
open class State {
var lastMessage: String? = null
}
}
I am trying to learn Kotlin and delegates are both interesting and confusing. I have a situation where, in a java class I would take a constructor arg, create a Future (the ID represents a resource in another system) and stash the Future as an instange variable. Then the "getXXX" would call Future.get()
Here is a sample java class
public class Example {
private Future<Foo> foo;
public Example(String fooId) {
this.foo = supplyAsync(() -> httpClient.get(fooId));
}
public Foo getFoo() {
return foo.get();
}
}
I am not supplying the Kotlin example because I am simply not sure how to construct it.
You can translate your Java code to Kotlin in a straightforward way using custom property getters:
class Example(fooId: Int) {
private val fooFuture = supplyAsync { httpClient.get(fooId) }
val foo: Foo
get() = fooFuture.get()
}
But Kotlin has a more powerful concept for generalizing property behavior -- the property delegates:
class Example {
val foo: Foo by someDelegate
}
In this example, someDelegate is an object that defines the behavior of property foo.
Though Future<V> cannot be used as a delegate out of the box in Kotlin, you can create your own property delegates by implementing getValue(thisRef, property) and (for mutable properties) setValue(thisRef, property, value) functions, thus explicitly providing the code to be executed when a property is read (and written, if mutable).
These functions can be either member functions for your project classes or extension functions, which fits the case with Future<V>. Basically, to use Future<V> as a property delegate, you have to define the getValue(thisRef, value) extension function for it, for example:
operator fun <V> Future<V>.getValue(thisRef: Any?, property: KProperty<*>) = get()
Here, the value the delegate will provide for a property will be simply taken from the Future::get call, but a proper implementation should probably take care of cancellation and exceptions handling. For this purpose, you can wrap a Future<V> into a class that will also define the fallback values/strategies, and then use this class' objects in by.
Then you can use Future<V> objects as delegates for your properties:
class Example(fooId: Int) {
val foo: Foo by supplyAsync { Thread.sleep(2000); fooId }
}
fun main(args: Array<String>) {
val e = Example(123)
println(e.foo)
}
To complete the answer from hotkey I propose this solution for a ReadWrite property
fun <V> Future<out V>.asDelegate(mayInterruptIfRunning: Boolean = false) =
object : ReadWriteProperty<Any?, V> {
private val lock = Object()
private var completedOrCanceled: Boolean = false
private var mValue: V? = null
override fun getValue(thisRef: Any?, property: KProperty<*>): V {
synchronized(lock) {
if (!completedOrCanceled) {
mValue = get()
completedOrCanceled = true
}
}
#Suppress("UNCHECKED_CAST")
return mValue as V
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: V) {
synchronized(lock) {
if (!completedOrCanceled) {
cancel(mayInterruptIfRunning)
completedOrCanceled = true
}
mValue = value
}
}
}
Usage could be :
class Example(fooId: Int) {
var foo: Foo by supplyAsync { Thread.sleep(2000); print("job done "); fooId }.asDelegate()
}
fun main(args: Array<String>) {
val e = Example(123)
println(e.foo) //"job done 123" printed after 2 sec
val f = Example(123)
f.foo = 456 //without waiting
println(e.foo) //"456" printed immediately
//"job done " printed after 2 sec
val g = Example(123) //"job done " printed after 2 sec
Thread.sleep(3000) //wait 3 sec then
println(e.foo) //"123" printed immediately
g.foo = 456
println(e.foo) //"456" printed immediately
}
note that if mayInterruptIfRunning is set to true then "job done " won't be printed if f.foo = 456 is called before the 2 sec