I want to make a class that can be declared with specific type operation. Like this (I don't know what this is called):
val div: Division = Division<Indonesia>("Division number 17th")
val div1 = Division<Palestine>("Division number 15")
Here is some other code:
class Division(name: String) {
// secret...
}
How I can make things like this:
Division<Indonesia>("How?")
You're talking about generics. Here's the Java docs covering the basics, here's the Kotlin-specific stuff. You give the class a generic type like this:
class Division<T>(name: String)
That's the most basic example... but I think you need to read the generics tutorial I linked
Related
When writing this example into the IDE:
enum class EnumTest {
FOO, BAR;
lateinit var foobar: String
}
I get the message With old Native GC, variable in enum class can't be changed after initialization on the "foobar" variable. I can't find anything about this message online. Also everything seems to work just fine, so my question is:
When and how does this affect me?
Thank you!
You could declare your values in a singleton object, set them there and reference it in the enum.
object Constants {
var FOO_STR = "bla"
var BAR_STR = "bar"
}
enum class EnumTest(val foobar: String) {
FOO(Constants.FOO_STR),
BAR(Constants.BAR_STR);
}
This code should work but also smells fishy.
Since an enum has an immutable flavor by design, I would not recommend this approach. I feel bad about posting this... but if your main problem is the resource heavy loading of these constants, maybe you do not need an enum to store those properties. Maybe just think of a simple singleton container with simple (named) properties.
In Kotlin, it's easy to pass a property as a KProperty or KProperty1 like this for example:
inline fun <TRet, reified TOwner> getName(property: KProperty1<TOwner, TRet>): String {
return "${TOwner::class.simpleName}.${property.name}"
}
And then given the following type:
class Example(val exampleName: String)
I could call getName(Example::exampleName) which would return Example.exampleName.
Is there any way to do this with enums?
Say I had the following enum class:
enum class ExampleEnum { VALUE1, VALUE2 }
Is there any way to get ExampleEnum::VALUE1 or some useful reflection object about the values in ExampleEnum? I essentially want to be able to access the declaring KClass (or java class) and the field being accessed in the enum, just by passing one argument.
The alternative is to write something like getName(ExampleEnum::class, "VALUE1") which is verbose and doesn't play well with refactorings/renames. Also, please note the getName is just an example, the actual use case is a bit more general.
I know how to get an annotation of an enum value in Java.
However Kotlin has its own reflection library and I feel there should be a better way to do the job.
Could please anybody post an example.
Just to be specific let's define an enum class
enum class Enum {
#SerialName("constant")
Constant
}
I need a function f(e: Enum): String so that f(Enum.Constant) == "constant".
You can use a similar approach with java by getting the field by name and then reaching out to the annotation using annotation class.
So if you have below enum and annotation class definitions;
enum class Enum {
#SerialName("constant")
Constant
}
annotation class SerialName(val value: String)
Then you can define the below function and call it as shown below;
fun getAnnotationValue(enum:Enum):String = enum.declaringClass.getField(enum.name).getAnnotation(SerialName::class.java).value
fun main(args: Array<String>) {
println(getAnnotationValue(Enum.Constant))
}
Hope this helps.
I did only a little research here, but it appears there isn't support for this in the Kotlin reflection library. In fact, I discovered the linter doesn't even correctly suggest an annotation target of FIELD for your annotation if you give it one that doesn't work for Enum values, and instead incorrectly offers to automatically add a target of CLASS.
The problem is that Enum values are basically static member fields, which don't exist in Kotlin except in Enum classes. And the reflection classes don't seem to provide a way to access this special case.
I am struggling however to come up with a use case for Enum value annotations that can't be solved using properties in the Enum constructor(s).
enum class MyEnum(val someConstant: String? = null) {
SomeValue("myConstant")
}
I am trying to learn Kotlin and TornadoFX. One thing I keep seeing is code like this:
val TextProperty = SimpleStringProperty()
var text by Textproperty
I've been reading up on the documentation
https://edvin.gitbooks.io/tornadofx-guide/content/part2/Property%20Delegates.html
so I've "absorbed" that they are useful for when values in a model change, but I need further help really grasping the concept. Something doesn't quite seem to be clicking. Does anyone have any examples, videos, etc. that demonstrate the purpose and usefulness of these property delegates?
The important point here is that JavaFX requires or at least prefers observable properties. Instead of declaring a mutable property, you would declare one of the JavaFX property types, depending on what property type you want (String, Double, Int etc). All you really need is to declare this property:
class Customer {
val ageProperty = SimpleIntegerProperty()
}
You can get by with just this, without using any delegates. However, if you want to mutate this property, you need to change the value property inside the property you defined, so the code looks like this:
customer.ageProperty.value = 42
This is cumbersome, so to make it simple, you'd want to add getters and setters. Doing this manually would look something like this:
val ageProperty = SimpleIntegerProperty()
var age: Int
get() = ageProperty.value
set(value) { ageProperty.value = value }
Now you can set the age of a Customer like this:
customer.age = 42
This is much more convenient, but you'd have to declare all that code for each property, so in TornadoFX we introduced property delegates that takes care of all that with a simple statement, so:
val ageProperty = SimpleIntegerProperty()
var age by ageProperty
The end result is the same, without you having to do any of the heavy lifting.
Just to be clear, this explains the property delegates, not why JavaFX properties are useful. JavaFX properties allow you to bind to a UI element, like a text field for example. Changes to the text field will be written back into the property, and changes to the property would be written back to the UI.
Once you can written something like
class C { var text by Textproperty }
all c.text = blabla will be compiled to TextProperty.setValue(c, ::text, blabla), and c.text will be compiled to TextProperty.getValue(c, ::text). This enables the library (the provider of TextProperty) to take over the operations on text.
Ref: https://kotlinlang.org/docs/reference/delegated-properties.html
Kotlin allows to name a function same as an existing class, e.g. HashSet with initializer function could be implemented like this:
fun <T> HashSet(n : Int, fn: (Int) -> T) = HashSet<T>(n).apply {
repeat(n) {
add(fn(it))
}
}
When used, it looks like a normal HashSet constructor:
var real = HashSet<String>()
var fake = HashSet(5) { "Element $it" }
Should this be avoided or encouraged and why?
UPD
In the updated coding conventions, there's a section on this topic:
Factory functions
If you declare a factory function for a class, avoid giving it the same name as the class itself. Prefer using a distinct name making it clear why the behavior of the factory function is special. Only if there is really no special semantics, you can use the same name as the class.
Example:
class Point(val x: Double, val y: Double) {
companion object {
fun fromPolar(angle: Double, radius: Double) = Point(...)
}
}
The motivation I described below, though, seems to still hold.
As said in documentation about the naming style:
If in doubt default to the Java Coding Conventions such as:
methods and properties start with lower case
One strong reason to avoid naming a function same to a class is that it might confuse a developer who will use it later, because, contrary to their expectations:
the function won't be available for super constructor call (if the class is open)
it won't be visible as a constructor through reflection
it won't be usable as a constructor in Java code (new HashSet(n, it -> "Element " + it) is an error)
if you want to change the implementation later and return some subclass instance instead, it will get even more confusing that HashSet(n) { "Element $it" } will construct not a HashSet but, for example, a LinkedHashSet
It's better to show it explicitly that it's a factory function, not a constructor, to avoid this confusion.
Naming a function same to a class is generally avoided in stdlib, too. Given SomeClass, in stdlib a preferred naming style for factory functions is someClassOf, someClassBy or whatever explains the semantics of the function best. The examples:
generateSequence { ... } and sequenceOf(...)
lazy { ... } and lazyOf(...)
compareBy { ... }
listOf(...), setOf(...), mapOf(...)
So, one should definitely have strong reason to have a function mimic a constructor.
Instead, a function's name might tell a user more (even everything) about its usage.
I agree with +hotkey. It's probably best to avoid confusion in this case.
If it's only used internally and all the other devs (if any) are okay with it, though, I'd say to go for it. Python acknowledges that idea and I love it. Heck, they go both ways, being okay with you naming a class in function case, too, if it feels more like it's acting like a function. But, Python doesn't have to deal with Java interop, so definitely don't do it for public code.