I wonder if a data class with one of the properties being a function, such as:
data class Holder(val x: Data, val f: () -> Unit)
can work at all, since the following test fails.
val a = {}
val b = {}
Assert.assertEquals(a, b)
Update: Use case for this could be to have a
data class ButtonDescriptor(val text: String, val onClick: () -> Unit)
and then flow it to UI whilst doing distinctUntilChanged()
I don't think this is possible, I'm afraid.
You can of course check reference equality (===, or == in this case because functions don't generally override equals()). That would give you a definite answer where you have references to the same function instance. But that doesn't check structural equality, and so reports the two lambdas in the question as different.
You can check whether the two functions are instances of the same class by checking their .javaClass property. If the same, that would imply that they do the same processing — though I think they could still have different variables/captures. However, if different, that wouldn't tell you anything. Even the simple examples in the question are different classes…
And of course, you can't check them as ‘black boxes’ — it's not feasible to try every possible input and check their outputs. (Even assuming they were pure functions with no side effects, which in general isn't true!)
You might be able to get their bytecode from a classloader, and compare that, but I really wouldn't recommend it — it'd be a lot of unnecessary work, you'd have to allow for the difference in class names etc., it would probably have a lot of false negatives, and again I think it could return the same code for two functions which behaved differently due to different parameters/captures.
So no, I don't think this is possible in JVM languages.
What are you trying to achieve with this, and could there be another way? (For example, if these functions are under your control, can you arrange for reference equality to do what you need? Or could you use function objects with an extra property giving an ID or something else you could compare?)
When you create your data class, if you pass the function by reference it will work with DiffUtils and distinctUntilChanged(). Function references do not break the isEquals() method of data classes in the same way that a lambda does.
For example, you create a function for your onClick:
private fun onClick() { // handle click }
and create your data class like
BottomDescriptor("some text", ::onClick)
Related
I need a key-value store (e.g. a Mapor a custom class) which only allows keys out of a previously defined set, e.g. only the keys ["apple", "orange"]. Is there anything like this built-in in Kotlin? Otherwise, how could one do this? Maybe like the following code?
class KeyValueStore(val allowedKeys: List<String>){
private val map = mutableMapOf<String,Any>()
fun add(key: String, value: Any) {
if(!allowedKeys.contains(key))
throw Exception("key $key not allowed")
map.put(key, value)
}
// code for reading keys, like get(key: String) and getKeys()
}
The best solution for your problem would be to use an enum, which provides exactly the functionality that you're looking for. According to the docs, you can declare an enum like so:
enum class AllowedKeys {
APPLE, ORANGE
}
then, you could declare the keys with your enum!
Since the keys are known at compile time, you could simply use an enum instead of String as the keys of a regular Map:
enum class Fruit {
APPLE, ORANGE
}
val fruitMap = mutableMapOf<Fruit, String>()
Instead of Any, use whatever type you need for your values, otherwise it's not convenient to use.
If the types of the values depend on the key (a heterogeneous map), then I would first seriously consider using a regular class with your "keys" as properties. You can access the list of properties via reflection if necessary.
Another option is to define a generic key class, so the get function returns a type that depends on the type parameter of the key (see how CoroutineContext works in Kotlin coroutines).
For reference, it's possible to do this if you don't know the set of keys until runtime. But it involves writing quite a bit of code; I don't think there's an easy way.
(I wrote my own Map class for this. We needed a massive number of these maps in memory, each with the same 2 or 3 keys, so I ended up writing a Map implementation pretty much from scratch: it used a passed-in array of keys — so all maps could share the same key array — and a private array of values, the same size. The code was quite long, but pretty simple. Most operations meant scanning the list of keys to find the right index, so the theoretic performance was dire; but since the list was always extremely short, it performed really well in practice. And it saved GBs of memory compared to using HashMap. I don't think I have the code any more, and it'd be far too long to post here, but I hope the idea is interesting.)
There are can be two ways of writing helper method in Kotlin
First is
object Helper {
fun doSomething(a: Any, b: Any): Any {
// Do some businesss logic and return result
}
}
Or simply writing this
fun doSomething(a: Any, b: Any): Any {
// Do some businesss logic and return result
}
inside a Helper.kt class.
So my question is in terms of performance and maintainability which is better and why?
In general, your first choice should be top-level functions. If a function has a clear "primary" argument, you can make it even more idiomatic by extracting it as the receiver of an extension function.
The object is nothing more than a holder of the namespace of its member functions. If you find that you have several groups of functions that you want to categorize, you can create several objects for them so you can qualify the calls with the object's name. There's little beyond this going in their favor in this role.
object as a language feature makes a lot more sense when it implements a well-known interface.
There's a third and arguably more idiomatic way: extension functions.
fun Int.add(b: Int): Int = this + b
And to use it:
val x = 1
val y = x.add(3) // 4
val z = 1.add(3) // 4
In terms of maintainability, I find extension functions just as easy to maintain as top-level functions or helper classes. I'm not a big fan of helper classes because they end up acquiring a lot of cruft over time (things people swear we'll reuse but never do, oddball variants of what we already have for special use cases, etc).
In terms of performance, these are all going to resolve more or less the same way - statically. The Kotlin compiler is effectively going to compile all of these down to the same java code - a class with a static method.
I asked a question at How to design a complex class which incude some classes to make expansion easily in future in Kotlin? about how to design a complex class which incude some classes to make expansion easily in future in Kotlin.
A expert named s1m0nw1 give me a great answer as the following code.
But I don't know why he want to change MutableList to List at https://stackoverflow.com/posts/47960036/revisions , I can get the correct result when I use MutableList. Could you tell me?
The code
interface DeviceDef
data class BluetoothDef(val Status: Boolean = false) : DeviceDef
data class WiFiDef(val Name: String, val Status: Boolean = false) : DeviceDef
data class ScreenDef(val Name: String, val size: Long) : DeviceDef
class MDetail(val _id: Long, val devices: List<DeviceDef>) {
inline fun <reified T> getDevice(): T {
return devices.filterIsInstance(T::class.java).first()
}
}
Added
I think that mutableListOf<DeviceDef> is better than ListOf<DeviceDef> in order to extend in future.
I can use aMutableList.add() function to extend when I append new element of mutableListOf<DeviceDef>.
If I use ListOf<DeviceDef>, I have to construct it with listOf(mBluetoothDef1, mWiFiDef1, //mOther), it's not good. Right?
var aMutableList= mutableListOf<DeviceDef>()
var mBluetoothDef1= BluetoothDef(true)
var mWiFiDef1= WiFiHelper(this).getWiFiDefFromSystem()
aMutableList.add(mBluetoothDef1)
aMutableList.add(mWiFiDef1)
// aMutableList.add(mOther) //This is extension
var aMDetail1= MDetail(myID, aMutableList)
Sorry for not giving an explanation in the first place. The differences are explained in the docs.:
Unlike many languages, Kotlin distinguishes between mutable and immutable collections (lists, sets, maps, etc). Precise control over exactly when collections can be edited is useful for eliminating bugs, and for designing good APIs.
It is important to understand up front the difference between a read-only view of a mutable collection, and an actually immutable collection. Both are easy to create, but the type system doesn't express the difference, so keeping track of that (if it's relevant) is up to you.
The Kotlin List<out T> type is an interface that provides read-only operations like size, get and so on. Like in Java, it inherits from Collection<T> and that in turn inherits from Iterable<T>. Methods that change the list are added by the MutableList<T> interface. [...]
The List interface provides a read-only view so that you cannot e.g add new elements to the list which has many advantages for instance in multithreaded environments. There may be situations in which you will use MutableList instead.
I also recommend the following discussion:
Kotlin and Immutable Collections?
EDIT (added content):
You can do this is a one-liner without any add invocation:
val list = listOf(mBluetoothDef1, mWiFiDef1)
In Kotlin, a function with at least one argument can be defined either as a regular non-member function or as an extension function with one argument being a receiver.
As to the scoping, there seems to be no difference: both can be declared inside or outside classes and other functions, and both can or cannot have visibility modifiers equally.
Language reference seems not to recommend using regular functions or extension functions for different situations.
So, my question is: when do extension functions give advantage over regular non-member ones? And when regular ones over extensions?
foo.bar(baz, baq) vs bar(foo, baz, baq).
Is it just a hint of a function semantics (receiver is definitely in focus) or are there cases when using extensions functions makes code much cleaner or opens up opportunities?
Extension functions are useful in a few cases, and mandatory in others:
Idiomatic Cases:
When you want to enhance, extend or change an existing API. An extension function is the idiomatic way to change a class by adding new functionality. You can add extension functions and extension properties. See an example in the Jackson-Kotlin Module for adding methods to the ObjectMapper class simplifying the handling of TypeReference and generics.
Adding null safety to new or existing methods that cannot be called on a null. For example the extension function for String of String?.isNullOrBlank() allows you to use that function even on a null String without having to do your own null check first. The function itself does the check before calling internal functions. See documentation for extensions with Nullable Receiver
Mandatory Cases:
When you want an inline default function for an interface, you must use an extension function to add it to the interface because you cannot do so within the interface declaration (inlined functions must be final which is not currently allowed within an interface). This is useful when you need inline reified functions, for example this code from Injekt
When you want to add for (item in collection) { ... } support to a class that does not currently support that usage. You can add an iterator() extension method that follows the rules described in the for loops documentation -- even the returned iterator-like object can use extensions to satisfy the rules of providing next() and hasNext().
Adding operators to existing classes such as + and * (specialization of #1 but you can't do this in any other way, so is mandatory). See documentation for operator overloading
Optional Cases:
You want to control the scoping of when something is visible to a caller, so you extend the class only in the context in which you will allow the call to be visible. This is optional because you could just allow the extensions to be seen always. see answer in other SO question for scoping extension functions
You have an interface that you want to simplify the required implementation, while still allowing more easy helper functions for the user. You can optionally add default methods for the interface to help, or use extension functions to add the non-expected-to-be-implemented parts of the interface. One allows overriding of the defaults, the other does not (except for precedence of extensions vs. members).
When you want to relate functions to a category of functionality; extension functions use their receiver class as a place from which to find them. Their name space becomes the class (or classes) from which they can be triggered. Whereas top-level functions will be harder to find, and will fill up the global name space in IDE code completion dialogs. You can also fix existing library name space issues. For example, in Java 7 you have the Path class and it is difficult to find the Files.exist(path) method because it is name spaced oddly. The function could be placed directly on Path.exists() instead. (#kirill)
Precedence Rules:
When extending existing classes, keep the precedence rules in mind. They are described in KT-10806 as:
For each implicit receiver on current context we try members, then local extension functions(also parameters which have extension function type), then non-local extensions.
Extension functions play really well with the safe call operator ?.. If you expect that the argument of the function will sometimes be null, instead of early returning, make it the receiver of an extension function.
Ordinary function:
fun nullableSubstring(s: String?, from: Int, to: Int): String? {
if (s == null) {
return null
}
return s.substring(from, to)
}
Extension function:
fun String.extensionSubstring(from: Int, to: Int) = substring(from, to)
Call site:
fun main(args: Array<String>) {
val s: String? = null
val maybeSubstring = nullableSubstring(s, 0, 1)
val alsoMaybeSubstring = s?.extensionSubstring(0, 1)
As you can see, both do the same thing, however the extension function is shorter and on the call site, it's immediately clear that the result will be nullable.
There is at least one case where extension functions are a must - call chaining, also known as "fluent style":
foo.doX().doY().doZ()
Suppose you want to extend the Stream interface from Java 8 with you own operations. Of course, you can use ordinary functions for that, but it will look ugly as hell:
doZ(doY(doX(someStream())))
Clearly, you want to use extension functions for that.
Also, you cannot make ordinary functions infix, but you can do it with extension functions:
infix fun <A, B, C> ((A) -> B).`|`(f: (B) -> C): (A) -> C = { a -> f(this(a)) }
#Test
fun pipe() {
val mul2 = { x: Int -> x * 2 }
val add1 = { x: Int -> x + 1 }
assertEquals("7", (mul2 `|` add1 `|` Any::toString)(3))
}
There are cases where you have to use extension methods. E.g. if you have some list implementation MyList<T>, you can write an extension method like
fun Int MyList<Int>.sum() { ... }
It is impossible to write this as a "normal" method.
I'm often running into the same trail of thought when I'm creating private methods, which application is to modify (usually initialize) an existing variable in scope of the class.
I can't decide which of the following two methods I prefer.
Lets say we have a class Test with a field variable x. Let it be an integer. How do you usually modify / initialize x ?
a) Modifying the field directly
private void initX(){
// Do something to determine x. Here its very simple.
x = 60;
}
b) Using a return value
private int initX(){
// Do something to determine x. Here its very simple.
return 60;
}
And in the constructor:
public Test(){
// a)
initX();
// b)
x = initX();
}
I like that its clear in b) which variable we are dealing with. But on the other hand, a) seems sufficient most of the time - the function name implies perfectly well what we are doing!
Which one do you prefer and why?
Thank for your answers guys! I'll make this a community wiki as I realize that there is no correct answer to this.
I usually prefer b), only I pick a different name, like computeX() in this case. A few reasons for why:
if I declare computeX() as protected, there is a simple way for a subclass to influent how it works, yet x itself can remain a private field;
I like to declare fields final if that's what they are; in this case a) is not an option since initialization has to happen in compiler (this is Java-specific, but your examples all look Java as well).
That said, I don't have a strong preference between the two methods. For instance, if I need to initialize several related fields at once, I will usually pick option a). That, though, only if I cannot or don't want for some reason, to initialize directly in constructor.
For initialization I prefer constructor initialization if it's possible,
public Test():x(val){...}, or write initialization code in the constructor body. Constructor is the best place to initialize all the fields (actually, it is the purpose of constructor). I'd use private initX() approach only if initialization code for X is too long (just for readability) and call this function from constructor. private int initX() in my opinion has nothing to do with initialization(unless you implement lazy initialization,but in this case it should return &int or const &int) , it is an accessor.
I would prefer option b), because you can make it a const function in languages that support it.
With option a), there is a temptation for new, lazy or just time-stressed developers to start adding little extra tasks into the initX method, instead of creating a new one.
Also, in b), you can remove initX() from the class definition, so consumers of the object don't even have to know it's there. For example, in C++.
In the header:
class Test {
private: int X;
public: Test();
...
}
In the CPP file:
static int initX() { return 60; }
Test::Test() {
X = initX();
}
Removing the init functions from the header file simplifies the class for the people that have to use it.
Neither?
I prefer to initialize in the constructor and only extract out an initialization method if I need a lot of fields initialized and/or need the ability to re-initialize at another point in the life time of an instance (without going through a destruct/construct).
More importantly, what does 60 mean?
If it is a meaningful value, make it a const with a meaningful name: NUMBER_OF_XXXXX, MINUTES_PER_HOUR, FIVE_DOZEN_APPLES, SPEED_LIMIT, ... regardless of how and where you subsequently use it (constructor, init method or getter function).
Making it a named constant makes the value re-useable in and of itself. And using a const is much more "findable", especially for more ubiquitous values (like 1 or -1) then using the actual value.
Only when you want to tie this const value to a specific class would it make sense to me to create a class const or var, or - it the language does not support those - a getter class function.
Another reason to make it a (virtual) getter function would be if descendant classes need the ability to start with a different initial value.
Edit (in response to comments):
For initializations that involve complex calculations I would also extract out a method to do the calculation. The choice of making that method a procedure that directly modifies the field value (a) or a function that returns the value it should be given (b), would be driven by the question whether or not the calculation would be needed at other times than "just the constructor".
If only needed at initialization in the constructor, I would prefer method (a).
If the calculation needs to be done at other times as well, I would opt for method (b) as it also makes it possible to assign the outcome to some other field or local variable and so can be used by descendants or other users of the class without affecting the inner state of the instance.
Actually only a) method behaves as expected (by analyzing method name). Method b) should be named 'return60' in your example or 'getXValue' in some more complicated one.
Both options are correct in my opinion. It all depeneds what was your intention when certain design was choosen. If your method has to do initialization only I would prefer a) beacuse it is simplier. In case x value is also used for something else somewhere in logic using b) option might lead to more consistent code.
You should also always write method names clearly and make those names corresponding with actual logic. (in this case method b) has confusing name).
#Frederik, if you use option b) and you have a LOT of field variables, the constructor will become a quite unwieldy block of code. Sometimes you just can't help but have lots and lots of member variables in a class (example: it's a domain object and it's data comes straight from a very wide table in the database). The most pragmatic approach would be to modularize the code as you need to.