I am new in Kotlin and I currently study about the concept of OOP
I am trying to do a cast with this code, but I'm facing an error:
open class Operations1(){
open fun sum(n1:Int , n2:Int):Int{
return n1+ n2
}
fun sub(n1:Int , n2:Int):Int{
return n1- n2
}
}
class multiOperations1():Operations(){
override fun sum(n1:Int , n2:Int):Int{
return n1+ n2 +5
}
fun mul(n1:Int , n2:Int):Int{
return n1* n2
}
fun div(n1:Int , n2:Int):Int{
return n1/ n2
}
}
fun main(args:Array<String>){
var oper = Operations()
var inlit = multiOperations1() as Operations1
println("Enter first number")
var n1:Int = readLine()!!.toInt()
println("Enter Second Number")
var n2:Int = readLine()!!.toInt()
var sum = inlit.sum(n1 , n2)
var sub = inlit.sub(n1 , n2)
println("Sum: " + sum)
println("Sub: " + sub)
}
Screen shot of the code
error:
To achieve you can use Gson and avoid boilerplate code.
var operation= Operations(....)
val json = Gson().toJson(operation)
val multiOperations:MultiOperations =Gson().fromJson(json, MultiOperations::class.java)
You seem to have both an Operations and an Operations1 class. Your multiOperations1 class inherits from Operations instead of Operations1, so you won't be able to cast it to Operations1 (unless Operations is a subclass of Operations1).
I assume you wanted to inherit from Operations1 instead, like this:
class multiOperations1(): Operations1() {
...
}
A note on conventions: class names in Kotlin usually follow Java conventions, and use upper camel case, so you should probably name your class MultiOperations1 instead.
Either you can use -
var inlit = multiOperations1() as Operations
You can typecast your derived class to parent class. In your case multiOperations1 class have a parent class Operations.
Just a suggestion start you class name like multiOperations1 from capital letter.
Related
Can anyone help me implement these methods in Kotlin?
I want to find min, max elements of array of numbers and also sort array in ascending order. Here is a code
class DataArray<Number>(vararg numbers: Number) {
private val array = mutableListOf<Number>(*numbers)
fun getMin() {
return array.minByOrNull { it! } //doesn't work
}
fun getMax() = array.max() //doesn't work
fun sort() = array.sort() //doesn't work
private fun <E> MutableList<E>.max(): Any { //was created to use in function above, but resulted in stack overflow
return this.max()
}
private fun <E> MutableList<E>.sort(): Any { //was created to use in function above, but resulted in stack overflow
return this.sort()
}
override fun toString(): String {
var str = ""
for(i in array)
str += "$i "
return str
}
}
fun main() {
val arr = DataArray(2, 5, 2, 6, 9, -3, 56, 16, 72, 8)
println(arr.getMax())
println(arr.getMin())
println(arr.sort())
print(arr)
}
Note that the word Number here declares a generic parameter called Number. It does not refer to kotlin.Number. You might have intended it to declare a generic parameter with a bound of Number instead, in which case you should have written:
class DataArray<T: Number>(vararg numbers: T) {
...
}
But even if you did, it still wouldn't work as Numbers are not comparable.
You would have to further constrain T to Comparable<T>:
class DataArray<T: Number>(vararg numbers: T) where T: Comparable<T> {
Then you can do:
fun getMin() = array.minOrNull()
fun getMax() = array.maxOrNull()
fun sort() = array.sort()
Extension functions on MutableList are unnecessary.
(Note that technically, the T: Number constraint is also unnecessary if you just want to use minOrNull, maxOrNull, and sort. I'm assuming you are planning on using one of the methods in kotlin.Number. Otherwise you can delete that constraint.)
You seem to be trying to implement your own MutableList by delegation. Keep in mind that you can easily do this using by:
class DataArray<T: Number>(
vararg numbers: T
) : MutableList<T> by mutableListOf(*numbers) {
override fun toString(): String {
var str = ""
for(i in this) // rather than "array", use "this"
str += "$i "
return str
}
}
I have this class (provides an implementation for a rational number) and I am having problems writing a secondary constructor - I need to do some computation on the value: String that I pass as a parameter and I don't know how to write that.
This is what I have right now, and it works. Most cases. The case that fails is when the string doesn't contain "/" aka when the denominator is 1.
data class Rational(val num:BigInteger, val den: BigInteger){
private val numerator
private val denominator
init{
denominator = when (den){
0.toBigInteger -> thrown IllegalArgumentException()
else -> den
}
numerator = num
}
constructor (value: String) :
this(value.split("/")[0].toBigInteger(), value.split("/")[1].toBigInteger())
}
How do I fix that?
Why does it have to be a constructor instead of a factory method? And even if it does, you can extract the logic into a helper (with slight complication because you need two values):
data class Rational(val num:BigInteger, val den: BigInteger){
...
private constructor (pair: Pair<BigInteger, BigInteger>) : this(pair.first, pair.second)
constructor (value: String) :
this(parseString(value))
companion object {
private fun parseString(value: String) =
if (value.contains("/")) {
val parts = value.split("/")
Pair(parts[0].toBigInteger(), parts[1].toBigInteger())
} else
Pair(value.toBigInteger(), 1.toBigInteger())
}
}
I am designing a DSL and run into a requirement where I have a variable which could be assigned to different ways. Greatly simplified, I would like to set value property either by an integer or by an expression in String. (The real need is even more complex.)
I would like to write in my DSL:
value = 42
or
value = "6*7"
Behind the scene, the value will be stored in a DynamicValue<Int> structure which contains either an integer or the expression.
class DynamicValue<T>(dv : T?, expr : String) {
val directValue : T? = dv
val script : String? = expr
...
}
I tried several ways (delegate, class, etc), but none of them provided these syntax.
Is there a way to declare this union like structure?
What do you think about the following syntax:
value(42)
value("6*7")
//or
value+=42
value+="6*7"
You can do this with operator functions:
class DynamicValue<T>() {
var dv: T? = null
var expr: String? = null
operator fun invoke(dv : T) {
this.dv = dv
this.expr = null
}
operator fun invoke(expr: String) {
this.dv = null
this.expr = expr
}
operator fun plusAssign(dv : T) {
this.dv = dv
this.expr = null
}
operator fun plusAssign(expr: String) {
this.dv = null
this.expr = expr
}
}
You can't redefine the assign operator in Kotlin, therefor the pure syntax value=42 is not possible.
But I wouldn't go with operator functions, it's to magical. I would do this:
val value = DynamicValue<Int>()
value.simple=42
value.expr="6*7"
class DynamicValue2<T>() {
private var _dv: T? = null
private var _expr: String? = null
var simple: T?
get() = _dv
set(value) {
_dv = value
_expr = null
}
var expr: String?
get() = _expr
set(value) {
_expr = value
_dv = null
}
}
Rene's answer gave me the lead and finally I turned up with this solution.
In this solution I took all my requirements in (the ones I dropped out in my original question) so this became much more complicated than my original question would have required.
My whole requirement was to be able to add static values or scripts (snippets) running on a well guarded context. These script would be stored, and executed later. I wanted to enable the whole power of the IDE when writing the script, but would like to guard my scripts from code injections and help the user to use only the context values the script requires.
The trick I used to achieve this is to enable adding script in kotlin, but before I run the whole DSL script and create the business objects, I convert the script into a string. (This string will be executed later in a guarded, wrapped context by JSR233 engine.) This conversation forced me to tokenize the whole script before execution and search/replace some of the tokens. (The whole tokenizer and converter is rather long and boring, so I won't insert here.)
First approach
What my goal was to be able to write any of this:
myobject {
value = static { 42 } // A static solution
value = static { 6 * 7 } // Even this is possible
value = dynamic{ calc(x, y) } // A pure cotlin solution with IDE support
value = dynamic("""calc(x * x)""") // This is the form I convert the above script to
}
where calc, x and y are defined in the context class:
class SpecialScriptContext : ScriptContextBase() {
val hello = "Hello"
val x = 29
val y = 13
fun calc(x: Int, y: Int) = x + y
fun greet(name: String) = println("$hello $name!")
}
So let's see the solution! First I need a DynamicValue class to hold one of the values:
class DynamicValue<T, C : ScriptContextBase, D: ScriptContextDescriptor<C>>
private constructor(val directValue: T?, val script: String?) {
constructor(value: T?) : this(value, null)
constructor(script: String) : this(null, script)
}
This structure will ensure that exactly one of the options (static, script) will be set. (Don't bother with the C and D type parameters, they are for context-based script support.)
Then I made top level DSL functions to support syntax:
#PlsDsl
fun <T, C : ScriptContextBase, D : ScriptContextDescriptor<C>> static(block: () -> T): DynamicValue<T, C, D>
= DynamicValue<T, C, D>(value = block.invoke())
#PlsDsl
fun <T, C : ScriptContextBase, D : ScriptContextDescriptor<C>> dynamic(s: String): DynamicValue<T, C, D>
= DynamicValue<T, C, D>(script = s)
#PlsDsl
fun <T, C : ScriptContextBase, D : ScriptContextDescriptor<C>> dynamic(block: C.() -> T): DynamicValue<T, C, D> {
throw IllegalStateException("Can't use this format")
}
An explanation to the third form. As I wrote before, I don't want to execute the block of the function. When the script is executed, this form is converted to the string form, so normally this function would never appear in the script when executed. The exception is a sanity warning, which would never be thrown.
Finally added the field to my business object builder:
#PlsDsl
class MyObjectBuilder {
var value: DynamicValue<Int, SpecialScriptContext, SpecialScriptContextDescriptor>? = null
}
Second approach
The previous solution worked but had some flaws: the expression was not associated with the variable it set, neither with the entity the value was set in. With my second approach I solved this problem and removed the need of equal sign and most of the unnecessary curly brackets.
What helped: extension functions, infix functions and sealed classes.
First, I split the two value types into separated classes defined a common ancestor:
sealed class Value<T, C : ScriptContextBase> {
abstract val scriptExecutor: ScriptExecutor
abstract val descriptor: ScriptContextDescriptor<C>
abstract val code: String
abstract fun get(context: C): T?
}
class StaticValue<T, C : ScriptContextBase>(override val code: String,
override val scriptExecutor: ScriptExecutor,
override val descriptor: ScriptContextDescriptor<C>,
val value: T? = null
) : Value<T, C>() {
override fun get(context: C) = value
constructor(oldValue: Value<T, C>, value: T?) : this(oldValue.code, oldValue.scriptExecutor, oldValue.descriptor, value)
}
class DynamicValue<T, C : ScriptContextBase>(override val code: String,
script: String,
override val scriptExecutor: ScriptExecutor,
override val descriptor: ScriptContextDescriptor<C>)
: Value<T, C>() {
constructor(oldValue: Value<T, C>, script: String) : this(oldValue.code, script, oldValue.scriptExecutor, oldValue.descriptor)
private val scriptCache = scriptExecutor.register(descriptor)
val source = script?.replace("\\\"\\\"\\\"", "\"\"\"")
private val compiledScript = scriptCache.register(generateUniqueId(code), source)
override fun get(context: C): T? = compiledScript.execute<T?>(context)
}
Note, that I made the primary constructor internal and created a kind of copy and alter constructor. Then I defined the new functions as extension of the common ancestor and marked them infix:
infix fun <T, C : ScriptContextBase> Value<T, C>.static(value: T?): Value<T, C> = StaticValue(this, value)
infix fun <T, C : ScriptContextBase> Value<T, C>.expr(script: String): Value<T, C> = DynamicValue(this, script)
infix fun <T, C : ScriptContextBase> Value<T, C>.dynamic(block: C.() -> T): Value<T, C> {
throw IllegalStateException("Can't use this format")
}
Using the secondary copy-and-alter constructor allows to inherit the context sensitive values. Finally I initialize the value inside the DSL builder:
#PlsDsl
class MyDslBuilder {
var value: Value<Int, SpecialScriptContext> = StaticValue("pl.value", scriptExecutor, SpecialScriptContextDescriptor)
var value2: Value<Int, SpecialScriptContext> = StaticValue("pl.value2", scriptExecutor, SpecialScriptContextDescriptor)
}
Everything is in place and now I can use it in my script:
myobject {
value static 42
value2 expr "6 * 7"
value2 dynamic { calc(x, y) }
}
Like the title says:
class Answers {
enum class Answer(text: String) {
YES("Yes."),
No("No."),
MAYBE("Maybe."),
AGAIN("Ask again.")
}
val answers = Answer.values()
val rand = Random()
fun genAnswer ():String {
val n = rand.nextInt(3)+1
// return Answer[answers[n]].text
}
}
I want to pick an enum element randomly and return its text property. However, it seems I can't use its value to retrieve the element.
You can get a random enum value by doing:
val randomAnswer = Answer.values().toList().shuffled().first().text
Keep in mind that it goes for convenience over performance.
Remember to expose the text property with val. For now, it's just a constructor param:
enum class Answer(val text: String)
Answer.values().random() will do the job for you in Kotlin.
When you write val/var within the constructor for a param, it declares a property inside the class. When you do not write it, it is simply a parameter passed to the primary constructor. So just add val to the constructor param text which will make it a property with a getter and above program will work..
import java.util.*
class Answers {
enum class Answer(val text: String) {
YES("Yes."),
No("No."),
MAYBE("Maybe."),
AGAIN("Ask again.")
}
val answers: Array<Answer> = Answer.values()
val rand = Random()
fun genAnswer ():String {
val n = rand.nextInt(3)+1
return answers[n].text
}
}
fun main(String: Array<String>) {
print(Answers().genAnswer())
}
I use this generic functions for any type of enum
/**
* return random enum value of enum class T
*/
inline fun <reified T : Enum<T>> randomEnum(): T {
val enumValues: Array<T> = enumValues()
return enumValues[(0 until enumValues.size).random()]
}
/**
* return random Int from start to end of range
*/
fun IntRange.random(): Int =
Random().nextInt((endInclusive + 1) - start) + start
I had a Enum SupportedLocale with values for languages
I did it in 2 steps
Get a list of values for enum:
val languages: Array<SupportedLocale> = SupportedLocale.values()
Now select random value using ordinate position
val randomLocale = languages[Random().nextInt(languages.size)]
An easy solution that I have used is
enum class OPERATOR(val symbol:String){MULTIPLY("*"),DIVIDE("/"),ADD("+"),SUBTRACT("-"),REMINDER("-")}
private fun getRandomOperator():String{
val limit=OPERATOR.values().size-1
return OPERATOR.values()[IntRange(0,limit).random()].symbol
}
Here is my function:
operator infix fun List<Teacher>.get(int: Int): Teacher {
var t = Teacher()
t.name = "asd"
return t ;
}
and my usage:
b[0].teachers[1].name
tip: b is an object that has List< Teacher > property
and the errorEmpty list doesn't contain element at index 1.
why this override operator function doesn't work?
In Kotlin, you cannot shadow a member function with an extension. A member always wins in the call resolution. So, you basically cannot call an extension with a signature same to that of a member function, that is present in the type that was declared or inferred for the expression.
class C {
fun foo() { println("member") }
}
fun C.foo() { println("extension") }
C().foo() // prints "member"
In your case, the member function is abstract operator fun get(index: Int): E defined in kotlin.collections.List.
See the language reference: Extensions are resolved statically
As voddan mentions in the comment, you can't overshadow a method with an extension. However, there is a way to get around this with some polymorphism. I don't think I would recommend doing this in your case, but I guess it shows off a cool Kotlin feature.
If b[0] returns an object of type B, you could do this in that class:
data class B(private val _teachers: List<Teacher> = emptyList()) {
private class Teachers(private val list: List<Teacher>) : List<Teacher> by list {
override operator fun get(int: Int): Teacher {
var t = Teacher()
t.name = "asd"
return t ;
}
}
val teachers: List<Teacher> = Teachers(_teachers)
}
fun main(args: Array<String>) {
println(B().teachers[0].name) // Prints "asd"
}
When I override the get-function it will affect everyone that uses the B class, not just where you would import the extension-function.
Note that I am delegating all other method-calls on the Teachers-class through to the underlying list.