There is integer variable 'a' in Class A, and method
Class A {
var a = 0
fun setA(int: Int) {
a = int
}
}
I used it in Class B by
Class B {
var classA = A()
classA.setA(10)
}
Then I want to set a to 100 in another class, Class C
But If I declare classA as A() and classA.setA(100) in same method of B, this doesn't change value of a referred in class B.
How to globally change the value of a in one place so that it's the same for all other classes?
class A {
companion object {
var a: Int = 0
}
}
perhaps you're looking for a companion object ? this allows global access to the same instance of a
you can now do:
A.a = 5
or in your case :
fun changeValue(int: Int) {
a = int
}
and this value will be the same everywhere
if you're trying to read the value back:
var example = A.a
note how I'm not creating an instance of A anywhere, because using a companion object is the same as using static in java, basically meaning that you can treat this as if an instance already exists
Related
I would like to cast an object based on one of it's fields, the field would have the right value for the object.
for example
object as object.class
object.class would be equivalent to a class, like Int or any other kotlin class.
is it possible?
yes you can do this if your Required class extend the base class
(list.get(pos) as Class).requeiedfunction
With an expected interface and a BaseClass you an accomplish this with type safety as needed. This is using objects as input, but following this pattern any type instance will work.
The interface forces the type to be assigned, and can allow you to maintain Type at scoping without any magic. It allows you to handle all expected cases easily.
interface ClassCast<out T> {
val type: T
}
open class MyClassBase
class MyClassOne : MyClassBase()
class MyClassTwo : MyClassBase()
class LonerClass
val myObjOne = object : ClassCast<MyClassBase> {
override val type = MyClassOne()
}
val myObjTwo = object : ClassCast<MyClassBase> {
override val type = MyClassTwo()
}
val nonRelatedObj = object : ClassCast<LonerClass> {
override val type = LonerClass()
}
fun castToClass(item: ClassCast<Any>): Any {
return when (item.type) {
is MyClassOne -> {
println("We have an Instance of class one")
MyClassOne()
}
is MyClassTwo -> {
println("We have an Instance of class two")
MyClassTwo()
}
is LonerClass -> {
println("Class that doesnt inherit from base type")
LonerClass()
}
else -> {
println("Unexpected type: $item")
throw Exception("Unexpected type cant be cast")
}
}
}
castToClass(myObjOne) // Prints: "We have an Instance of class one"
castToClass(myObjTwo)) // Prints: "We have an Instance of class two"
castToClass(nonRelatedObj) // Prints: "Class that doesnt inherit from base type"
I need to inherit the Object A from Object B, were both the objects consist of constants only.
Example
Object A {
const val a1 = "some_data_1"
const val a2 = "some_data_2"
}
Object B : A {
const val b1 = "some_data_3"
}
is it feasible to achieve this in kotlin ?
Kotlin is an object-oriented programming (OOP) language. We can inherit object A from object B for that we have to to allow class "A" to be inherited, for that we need to attach the open modifier before the class to make it non-final.
For the const we have to use companion object, which is an object that is common to all instances of that class.
open class A {
companion object {
const val a1 = "some_data_1"
const val a2 = "some_data_2"
}
}
class B : A() {
companion object {
const val b1 = "some_data_3"
}
val a_1 = a1
val a_2 = a2
}
Check this link to understand inheritance
Check this link to understand Companion Object
open class A {
companion object {
const val a1 = "some_data_1"
const val a2 = "some_data_2"
}
}
class B : A() {
companion object {
const val b1 = "some_data_3"
}
val a_1 = a1
val a_2 = a2
}
for a class to be inherited in Kotlin it should be open for example open class A {}
for class B to extends class A should add the class B : A()
for constants should be inside a companion object {}
I would probably dive a bit deeper.
Object in your example is an Object Declaration.
You should have a look at this doc describing Object Declarations and Object Expressions.
The question is - Why would you need to have one class only with constants extend another(also containing only const vals)?
Object Declarations are Kotlin built in Singletons and BTW are thread safe.
Example :
object DeviceProvider {
private val _devices = ArrayList<Device>()
fun getDevices() = _devices as List<Device>
fun registerDevice(device: Device) {
_devices.find { it == device } ?: _devices.add(device)
}
}
Usage :
fun addDevice(){
ServiceProvider.registerDevice(Device("1234"))
}
Object declarations are allowed to extend open classes and interfaces - so you can define a behavior or even a state via inheritance. As usual you can have a look at Kotlin docs about inheritance, those are exhaustive and nice read.
Still if we are talking about common approaches defining const values - then separate file is the best solution, if of course that value should be bound to any specific class. Here is a nice point of view(thanks Marko for your answer) :
In Java you're forced to put all static field and method declarations
in a class and often you even have to create a class just for that
purpose. Coming to Kotlin, many users look for the equivalent facility
out of habit and end up overusing companion objects.
Kotlin completely decouples the notions of a file and a class. You can
declare any number of public classes is the same file. You can also
declare private top-level functions and variables and they'll be
accessible only to the classes within the same file. This is a great
way to organize closely associated code and data.
I wanted to know how I define a static variable in Kotlin that can be used in other classes that do not final. Because the data is changing.
Example Java:
public static Boolean ActivityIsRuning = false;
There are three ways to achieve this:
1) Top-level / global declaration
Declare a variable outside of any class or function and it will be accessible from anywhere:
var activityIsRunning = false
2) object (an out of the box singleton)
object StaticData {
var activityIsRunning = false
}
Accessable like this:
StaticData.activityIsRunning
3) Class with companion object (as Todd already suggested)
class Config {
companion object {
var activityIsRunning = false
}
}
Accessable like this:
Config.activityIsRunning
You have to create companion object for this.
Your code in Kotlin would look something like this:
class Foo {
companion object {
lateinit var instance: Foo
}
init {
instance = this
}
}
You can define static variables in the companion object of any class. If you make it a var instead of a val, it can change values:
class MyClass {
companion object {
var activityIsRunning: Boolean = false
}
}
Adding to #Todd and #Willi Mentzel, if you like to group those settings under a common area, you can use a top-level plain object.
object GlobalSettings{
var isHomeActivityRunning = false
var isDrinkingCocoCola = true
}
and this can be accessed anywhere in the code (inside an Activity, Service, or anywhere) like this:
if( GlobalSettings.isDrinkingCocoCola ){
// do something
} else {
GlobalSettings.isDrinkingCocoCola = false
}
We are trying to set the value of a global variable declared in the code below
class MyApplication: Application() {
var globalVar = 2
}
Now we have a Main Activity that has a Edit Text named etPerson we would like to enter a value in etPerson and set the entered value equal to globalVar
Why because we want to make a call to a database function in another Activity
Here is the code that makes the call to the DB
var mApp = MyApplication()
var intGlobalVar = mApp.globalVar
println("############################ globalINT = "+intGlobalVar)
var ITEM = db.getItem(intGlobalVar)
println("%%%%%%%%%%%%%%%%%% ITEM "+ITEM?.id+" name "+ITEM?.name)
And for clarity here is the DB function
fun getItem(id: Int): Contact? {
val db = this.writableDatabase
val selectQuery = "SELECT * FROM $TABLE_NAME WHERE $colId = ?"
db.rawQuery(selectQuery, arrayOf(id.toString())).use {
// .use requires API 16
if (it.moveToFirst()) {
val result = Contact(0)
result.id = it.getInt(it.getColumnIndex(colId))
result.name = it.getString(it.getColumnIndex(colName))
return result
}
}
return null
}
So the issue is setting the var globalVar to the value entered in etPerson on the Main Activity
The concept can be accomplished using put and get with intents but that is not our goal here
Our question is how to set the globalVar to the value entered in the Edit Text?
When your app starts one and only one object of the class MyApplication() will be created, so you don't need:
var mApp = MyApplication()
You can access MyApplication() and all its members from everywhere in your app.
Declare a companion object in MyApplication() and put globalVar's declaration inside:
class MyApplication: Application() {
companion object {
var globalVar = 2
}
override fun onCreate() {
super.onCreate()
// initialization code here
}
}
So in your MainActivity class or elsewhere you can use MyApplication.Companion.globalVar to get or set its value.
Or you can import the globalVar variable in any class like:
import yourpackagename.MyApplication.Companion.globalVar
and refer to it simply globalVar
You also need to declare MyApplication in the manifest:
<application
android:name=".MyApplication"
I use this way to send an Intent :
Target activity or class or object (Reciver):
class ReturnActivityIntent private constructor() {
var data: Intent? = null
companion object {
val instance = ReturnActivityIntent()
}
}
In the MainActivity (Sender)
val returnActivityIntent: Notifications.ReturnActivityIntent = Notifications.ReturnActivityIntent.instance
returnActivityIntent.data = Intent(this, MainActivity2::class.java)
so you can change or share variables in this way
package example
class Apple {
val APPLE_SIZE_KEY: String = "APPLE_SIZE_KEY"
}
Class:
package example
class Store {
fun buy() {
val SIZE = Apple.APPLE_SIZE_KEY
}
}
Error:
'APPLE_SIZE_KEY' has private access in 'example.Apple'
But official documentation describes that if we do not specify any visibility modifier, public is used by default.
Why is above error coming?
What you are trying to do is accessing a value of a class that has no instance. Here are three solutions:
package example
object Apple {
val APPLE_SIZE_KEY: String = "APPLE_SIZE_KEY"
}
This way you do not need to instantiate anything because of the way objects work in Kotlin.
You could also just instantiate your class like this:
package example
class Store {
fun buy() {
val SIZE = Apple().APPLE_SIZE_KEY
}
}
In this solution you also have an object of Apple, but Apple is still declared as a class.
The third option is a companion object, which behaves like static variables in Java.
package example
class Apple {
companion object {
val APPLE_SIZE_KEY: String = "APPLE_SIZE_KEY"
}
}
If you want this to be a class level property instead of an instance level property, you can use a companion object:
class Apple {
companion object {
val APPLE_SIZE_KEY: String = "APPLE_SIZE_KEY"
}
}
fun useAppleKey() {
println(Apple.APPLE_SIZE_KEY)
}
What you currently have is an instance property, which you could use like this:
fun useInstanceProperty() {
val apple = Apple()
println(apple.APPLE_SIZE_KEY)
}