Returning a class in Kotlin - kotlin

class Wolf {
var hunger = 10
val food = "meat"
fun eat() {
println("The Wolf is eating $food")
}
}
class MyWolf {
var wolf: Wolf? = Wolf()
fun myFunction() {
wolf?.eat()
}
}
fun getAlphaWolf(): Wolf? {
return Wolf()
}
fun main(args: Array<String>) {
var w: Wolf? = Wolf()
if (w != null) {
w.eat()
}
var x = w?.hunger
println("The value of x is $x")
var y = w?.hunger ?: -1
println("The value of y is $y")
var myWolf = MyWolf()
myWolf?.wolf?.hunger = 8
println("The value of myWolf?.wolf?.hunger is ${myWolf?.wolf?.hunger}")
var myArray = arrayOf("Hi", "Hello", null)
for (item in myArray) {
item?.let { println(it) }
}
getAlphaWolf()?.let { it.eat() }
w = null
var z = w!!.hunger
}
This above code is extracted from a Kotlin textbook.
I have problem with the following:
fun getAlphaWolf(): Wolf? {
return Wolf()
}
As there is only a class called Wolf but no variable called Wolf in the code.
I wonder if it is possible to return a class inside a function?
What is the output if a class is returned inside a function?

If you are familiar with Java, then this Kotlin is equivalent to:
public class Application {
public Wolf getAlphaWolf() {
return new Wolf();
}
}
So, in Kotlin you are calling the no-arguments constructor. If you want to return the class Wolf, then that is also possible:
fun getWolfClass(): KClass<Wolf> {
return Wolf::class
}

In the following code, the primary constructor of class Wolf is called:
fun getAlphaWolf(): Wolf? {
return Wolf()
}
So, getAlphaWolf returns a completely new instance of Wolf with default values: Wolf(hunger=10,food=meat).
Update: by the way, making the return type of this function nullable is redundant, because a new instance cannot be null.

Related

did kotlin methods'param Int could be modified?

the fun of superclass like this:
fun onTrigger(params: P) {
if (!funA(params)) {
return
}
val request = funB(params)
}
funA and funB is abstract fun , implement in subclass like this(the generic P is Int):
fun funA(params:Int): Boolean {
if (params < 0) {
return false
}
}
fun funB(params:Int) {
val item = dataList[params]
}
accidental appearance crash:
java.lang.ArrayIndexOutOfBoundsException: length=10; index=-1
the params can be -1? why?

Kotlin: Programing is printing kotlin.unit

My Kotlin Class will run but it prints out the words: kotlin.Unit. What do I need to change?
fun main(args: Array<String>) {
var myDuck = Duck()
println(myDuck.quack())
}
class Duck() {
fun quack () {
println("Quack, Quack, Quack")
}
}
It is printing that because you are printing the return type of a function that does not return any value. If you are familiar with other languages it is the same as having a void return type.
In kotlin a funtion without a return type returns a unit type, and so when you print the return value of Duck::quack you are printing the string value of a Unit value.
The simplest solution is to not print the return value of Duck::quack; however, if you would like the prinlt to print the return of Duck::quak, it needs to return a useful value. For examle:
class Duck() {
fun quack(): String {
return "Quack, Quack, Quack"
}
}
fun main(args: Array<String>) {
var myDuck = Duck()
println(myDuck.quack())
}
or more idiomatically:
class Duck() {
val quack: String = "Quack, Quack. Quack"
}
fun main(args: Array<String>) {
var myDuck = Duck()
println(myDuck.quack)
}
It's anought to call
myDuck.quack()
wich has already println inside. Calling println(myDuck.quack()) prints type of myDuck.quack because it doesn't return any value.
1.prints "kotlin.Unit" if you don't specify the type
fun main(args: Array<String>) {
var myDuck = Duck()
println(myDuck.quack())
}
class Duck():String {
fun quack () {
return "Quack, Quack, Quack"
}
}
Also as shortly:
fun main() {
println(Duck.quack())
}
class Duck() {
fun quack () = "Quack, Quack, Quack"
}

How to assign current class instance in Kotlin

I have code which looks something like,
data class X{
fun getSomething(){
var y: Y()
//How can I write this
//this=y.doSomething()
}
}
class Y{
fun doSomething(): X{
//...
return x }
}
I want to assign this to an object that I am returning from some other method in some other class.
You cannot assign anything to this and also, data classes should be immutable. Just reassign your reference:
data class X(val x: String) {
fun getSomething() = Y().doSomething()
}
class Y {
fun doSomething(): X {
return X("fromY")
}
}
fun main(args: Array<String>) {
val second = X("first").getSomething()
}

Instantiating type T in Kotlin

In short, I would like to omit the repeated getT() in the example below. I have read Instantiating a generic type in Kotlin, but what does it mean 'to take () -> T as a parameter'? How can I apply that to below?
interface Food
{
var isHeated:Boolean;
var name:String;
}
abstract class Cooker<T:Food>
{
abstract fun getT():T;
abstract fun enhance(t:T);
fun cook(): T
{
var food = getT();
food.isHeated = true;
food.name = "heated " + food.name;
enhance(food);
return food;
}
}
class PotatoChip:Food
{
override var isHeated = false;
override var name = "potato chip";
}
class PotatoChipCooker:Cooker<PotatoChip>()
{
override fun getT(): PotatoChip {
return PotatoChip();
}
override fun enhance(t:PotatoChip)
{
t.name = "salted " + t.name;
}
}
class Pancake:Food
{
override var isHeated = false;
override var name = "pancake";
}
class PancakeCooker:Cooker<Pancake>()
{
override fun getT(): Pancake {
return Pancake();
}
override fun enhance(t:Pancake)
{
t.name = t.name + " coated with maple syrup";
}
}
fun main(args: Array<String>)
{
val result = PotatoChipCooker().cook();
println(result.name);
val result2 = PancakeCooker().cook();
println(result2.name);
}
You could make the initialization function part of the primary constructor. As a result, implementing classes will have to pass a function that specifies how the corresponding type is being created:
abstract class Cooker<T : Food>(private val initT: () -> T) {
abstract fun enhance(t: T)
fun cook(): T {
val food = initT()
food.isHeated = true
food.name = "heated $name"
enhance(food)
return food
}
}
class PotatoChipCooker : Cooker<PotatoChip>({ PotatoChip() }) {
override fun enhance(t: PotatoChip) {
t.name = "salted ${t.name}"
}
}
class PancakeCooker : Cooker<Pancake>({ Pancake() }) {
override fun enhance(t: Pancake) {
t.name = "${t.name} coated with maple syrup"
}
}
Note that I removed the optional semicolons and used string templates instead of concatenations. Also, the cook method can be simplified to:
fun cook() = initT().apply {
isHeated = true
name = "heated $name"
enhance(this)
}

Is possible to change dynamically method for an instance?

I wrote down this code:
open class Test(){
override fun toString(): String {
return "This is test!"
}
}
fun createTestX(): Test {
return object : Test() {
override fun toString(): String {
return super.toString() + "XXX"
}
}
}
fun main(args: Array<String>) {
val x = createTestX()
println(x)
}
It works as expected but I am curious whether is it possible to change method of instance using for example lambda like this:
val x = Test()
x.toString = () -> x.toString() + "XXX"
What you can do
class C {
var example:()->String = this::toString
}
fun main(args: Array<String>) {
val c = C()
println(c.example())
c.example = {"ABCDEF"}
println(c.example())
}
Limitations
Although this works for swapping fields, you cannot use it to override methods. This can be worked around by defining the method to invoke the field.
class C {
var example:()->String = {"ABC"}
override fun toString() = example()
}
fun main(args: Array<String>) {
val c = C()
println(c)
c.example = {"DEF"}
println(c)
}
Output:
ABC
DEF