how to instantiate an object from a class in kotlin - android

I am learning Kotlin, and I googled how to create a class in kotlin. So, I created the below class as a test.
In the main activity, I am trying to instantiate an object from the class Board, but i get the following error:
classifier Board does not have a companion object
please let me know how to intantiate an object of an the class Board?
MainActivity:
class ActMain : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.layout_act_main)
Board board = new Board(name = "ABC");
}
}
Board.kt:
data class Board(val name: String) {
var age: Int = 0
}

Kotlin does not use new.
Board board = new Board(name = "ABC");
is incorrect. Use
val board = Board("ABC")
Your code reflects the Java syntax... sort of. Kotlin has type inference, so you don't need to specify the class type. However, if you do specify it, it's different from Java:
val board: Board = Board("ABC")
Semi-colons are also not generally used in Kotlin, although they won't break the compilation if you use them.
name = "ABC" just isn't valid syntax no matter if it's Java or Kotlin. Actually it is (from #hotkey): https://kotlinlang.org/docs/reference/functions.html#named-arguments

Unlike Java, in Kotlin this is the correct way
MainActivity.kt
class ActMain : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.layout_act_main)
val board = Board("ABC")
board.age = 12
}
}
Board.kt
class Board(val name: String) {
var age: Int = 0
}

try to forget java
val board = Board("name")

in kotlin
when you want to declare new object yon can do like this.
val board = Board("ABC")
if you declare object by using val keyword. it look as you use final in java. the variable which you declared can not recreate again.
var board = Board("ABC")
if you use var to declare it look as normal variable in java
Anyway in kotlin you will see something that It doesn't contain in java such as
scoping function as link below. it will help you write your code is more easily.
https://kotlin.guide/scoping-functions
I hope this help :)

Related

Is there a way to place override function in a separate file in Kotlin?

I have a Kotlin class that is becoming very large (a couple of hundreds of lines). It's mainly because this class is the listener of several interfaces. Usually, I split my class functions with extensions (and place them in separate files). However, when I try that with override functions, Android Studio gives me this error:
"Modifier 'override' is not applicable to 'top level function'"
So, is there a workaround? How would you split a large file with many override functions? (In Swift, this is done using extensions or Partials in C#). Here is an image for reference in Android Studio and in Xcode. In Swift, we simply add "extension" and that allows us to write code as if we were writing right within the class:
Instead of having your Activity implement listener interfaces, make them into anonymous object members. I think this is usually cleaner anyway.
class MyActivity: AppCompatActivity() {
private lateinit var binding: MyActivityBinding
private val someButtonListener = OnClickListener {
binding.text = "Button clicked!"
}
override fun onCreate(savedInstanceState: Bundle) {
super.onCreate(savedInstanceState)
binding = MyActivityBinding.inflate(layoutInflater)
binding.button.onClickListener = someButtonListener
}
}
Then, you could break these out into another file by making functions that create them.
class MyActivity: AppCompatActivity() {
private lateinit var binding: MyActivityBinding
override fun onCreate(savedInstanceState: Bundle) {
super.onCreate(savedInstanceState)
binding = MyActivityBinding.inflate(layoutInflater)
binding.button.onClickListener = createSomeButtonListener(binding)
}
}
fun createSomeButtonListener(binding: MyActivityBinding) = OnClickListener {
binding.text = "Button clicked!"
}
If you need to call functions in the Activity from these listeners, you'll have to make your Activity a parameter of the function and expose those functions as public, unfortunately. It's not really proper encapsulation, but you typically don't reference Activities from other classes ever, so it's probably not a big deal for it to have some public functions.
This is my code inspired by the answer:
interface MyInterface {
fun itHappened()
}
class MyClass {
lateinit var listener: MyInterface
}
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val myObj = MyClass()
myObj.listener = anonymousListener()
myObj.listener.itHappened()
}
}
fun MainActivity.anonymousListener() = object : MyInterface {
override fun itHappened() {
Log.d("MyTag", "Clicked")
}
}

Kotlin Class causes App to crash

I tried to incorporate classes into my program, but now I can't get my program to work (no errors, just crashes). I have isolated the part that causes the crash in an extra project. Can someone help me?
package com.mietvertrag.simon.test
imports...
class MainActivity : AppCompatActivity() {
data class Contract(var adr:CharSequence, var dat:CharSequence, var mitr:CharSequence, var num:CharSequence)
lateinit var v1: Contract
lateinit var vertrag1: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
v1.adr = "Treestreet 24"
vertrag1 = findViewById(R.id.text)
}
}
You're trying to set a value to a property of a class instance that has not been initialized:
v1.adr = "Treestreet 24"
So initialize it:
v1 = Contract("Treestreet 24", "", "", "") <br/>
As for the no errors, just crashes:
you must use the Logcat to review the errors or you will never succeed in building apps.
I think the problem is v1 not initialize yet.

add extension on Log in android (Kotlin)

I use this code to add extension for Log class android
fun Log.i2(msg:String):Unit{
Log.i("Test",msg)
}
when using in the activity
class MainActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.i2("activity_main")
}
}
Log.i2 not found. What's wrong?
To achieve extension function in static class, you need to write extension of the companion object(refer this)
fun Log.Companion.i2(msg:String) {
...
}
You have created Extension function of Class Log.
Which is suppose to call by Instance of Class Log. You are trying to treat extension function as static and calling it by Class name. Which is not correct in the case
Currently, static extension methods in Kotlin is not supported without the companion object, because android.util.Log is a java class, so there is no companion object.
Instead, I recommend you to use a static function (package-level function, simply declared outside a class in a source code file):
fun logI2(msg: String) {
Log.i("Test", msg)
}
And just use it like this:
logI2("activity_main")

Convenient Kotlin LoggerFactory simplification

What is the most convenient way to use SLF4J or other logging approaches with kotlin?
Usually the developer is busy with boilerplate code like
private val logger: Logger = LoggerFactory.getLogger(this::class.java)
in each and every class to get a proper logger?
What are the most convenient ways to unify/simplify this with Kotlin?
You can define an extension property on every type:
val <T : Any> T.logger: Logger
get() = LoggerFactory.getLogger(this::class.java)
use it as follows:
class X {
init {
logger.debug("init")
}
}
Here's a simple example which returns a lazily-initialized logger from a bound callable reference or a standard property. I prefer calling from a callable reference because the :: denotes reflection (related to logging).
The class which provides the Lazy<Logger>:
class LoggingProvider<T : Any>(val clazz: KClass<T>) {
operator fun provideDelegate(inst: Any?, property: KProperty<*>) =
lazy { LoggerFactory.getLogger(clazz.java) }
}
Inline functions to call them:
inline fun <reified T : Any> KCallable<T>.logger() =
LoggingProvider(T::class)
inline fun <reified T : Any> T.logger() =
LoggingProvider(T::class)
Here's an example of using them. The require assertion in the initializer shows that the loggers share a reference:
class Foo {
val self: Foo = this
val logger by this.logger()
val callableLogger by this::self.logger()
init {
require(logger === callableLogger)
}
}
I define this function in my projects to make defining a logger easier for me. It takes advantage of Kotlin's reified types.
// Defined in Utilities.kt
inline fun <reified T:Any> logFor() =
LoggerFactory.getLogger(T::class.java)
Usage:
class MyClass {
private val log = logFor<MyClass>()
...
}
Or if you are creating a lot of them:
class MyClass {
companion object {
private val log = logFor<MyClass>()
}
...
}
if you don't like the boilerplate, you can always wrap the log.info with your own logger helper:
mylog.info(this, "data that needs to be logged")
Then in the background, have some sort of hashmap that keeps track of classes of the this param that can instantiate a logger for that class.
Other options might be using AspectJ Weaving to weave a logger into each class, but this is overkill in my opinion.
I have defined a utility method for this
fun getLogger(cl: KClass<*>): Logger {
return LoggerFactory.getLogger(cl.java)!!
}
and now in each class I can use the logger like this
companion object {
private val logger = getLogger(MyClass::class)
}

Unable to set ViewModel on Kotlin

New to Kotlin language, trying Android Architecture Components. Trying to set a ViewModel for my LifecycleActivity in Kotlin language:
class FooActivity : LifecycleActivity() {
private var mViewModel: FooViewModel? = null
..
override fun onCreate(savedInstanceState: Bundle?) {
mViewModel = ViewModelProviders.of(this).get(FooViewModel.class) <-- error here
Getting Name expected: and expecting )
What am I missing?
The class usage is wrong. With Kotlin you use: FooViewModel::class.java

Categories

Resources