Using class variables within an instance of a class - cocoa-touch

I'm trying to use Swift to create an instance of a class (the class being the desired type) but it would seem that when I initialize the instance the class var is not applied to the new instance. I'm sure there's an init call or something that I'm missing, so any help would be greatly appriciated.
class Person: NSObject {
private struct personNameStruct { static var _personName: String = "" }
class var personName: String
{
get { return personNameStruct._personName }
set { personNameStruct._personName = newValue }
}
}
var testPerson: Person
testPerson.personName = "Foo" //"'person' does not have a member named 'personName'"

An instance member is referred to through a reference to an instance.
A class member is referred to through a reference to the class.
So, for example:
class Dog {
class var whatDogsSay : String {
return "Woof"
}
func bark() {
println(Dog.whatDogsSay)
}
}
To make a dog bark, make a dog instance and tell it to bark:
let d = Dog()
d.bark()
To find out what dogs say, talk to the dog class:
let s = Dog.whatDogsSay

It works for me in a Playground if you access the personName variable using the class name person, not the instance name: person.personName = "Foo".
This is because a class variable in Swift is similar to a static variable in languages like Java and C#, in that it is shared between all instances of that class. If you just want a property in your class you shouldn't declare it as class var but just var.

Related

How to change return type based on a function input which is a class name?

I have multiple data classes and each class has a corresponding class containing more info. I want to write a function in which I should be able to pass an identifier (table name corresponding to the data class). Based on this identifier, object of the corresponding class should be made, the value changed and this object should be returned as output of the function. I have written a simplified version of it on playground but I am unable to get it to work. Any help is appreciated.
class someClass(
)
class objectForSomeClass(
var value: String
)
class someOtherClass(
)
class objectForSomeOtherClass(
var value: String
)
class doSomething() {
companion object {
val classMap = mapOf(
"someClass" to objectForSomeClass::class,
"someOtherClass" to objectForSomeOtherClass::class,
)
}
// Create a map of class name to a new object based on the class name input
fun dummyFun(className: String, valueInput: String): Map<String, kotlin.Any> {
var returnObject = mutableListOf<Pair<String, kotlin.Any>>()
when(className) {
"SOME_CLASS" -> {
returnObject = mutableListOf<Pair<String, justDoIt.classMap["someClass"]()>>()
}
"SOME_OTHER_CLASS" -> {
returnObject = Map<String, justDoIt.classMap["someOtherClass"]()>
}
}
returnObject[className].value = valueInput
return returnObject
}
}
fun main() {
var obj = doSomething()
var t = obj.dummyFun("SOME_CLASS", "Value to be inserted")
// do something with t
}
Not knowing more about your classes (the ones in your code are not data classes – a data class in Kotlin is a specific type of class) I still think a lot could be simplified down to maybe even this:
fun createObject(className: String, value: String): Any? {
return when (className) {
"SomeClass" -> ObjectForSomeClass(value)
"SomeOtherClass" -> ObjectForSomeOtherClass(value)
// ...
else -> null
}
}
Additionally:
The classMap is not necessary, you can hard-code the cases in the when clause as in my example. There is also no need for reflection, which you would need to create instances from SomeType::class.
With getting rid of classMap you also do not need the companion object holding it anymore, and then you are left with one function for creating instances of your classes, and this function does not have to be in a class. You might put it into a singleton class called object in Kotlin (https://kotlinlang.org/docs/object-declarations.html#object-expressions)
Data classes in Kotlin: https://kotlinlang.org/docs/data-classes.html
You could maybe also replace each class someClass & class objectForSomeClass pair with a class someClass with a companion object.

How to get both static and instance access to a classes field

Suppose I have an abstract superclass A. That class has a property abstract val predicate: (ModelClass) -> Boolean.
Let B be a subclass.
I want to be able to do both of the following:
Use the predicate from an instance aInstance.predicate
Also use that predicate elsewhere, without having to create an instance to get that predicate B.predicate
How can I do this.
I don't think this is possible.
There is no such thing as an abstract static method in Kotlin or Java.
Perhaps this will give more insight.
Does your class need to be abstract? Maybe the code below can be useful:
open class MyClass {
companion object myCompanion {
val myStatic = "MyClass"
}
open val myStatic = myCompanion.myStatic
}
class MySubClass : MyClass() {
companion object myCompanionSubClass {
val myStatic = "MySubClass"
}
override var myStatic = myCompanionSubClass.myStatic
}
fun main() {
println(MyClass.myStatic)
val t = MyClass()
println(t.myStatic)
println(MySubClass.myStatic)
val subClass = MySubClass()
println(subClass.myStatic)
}
In this code you can define a static property and use it from the class or any instance. It is also possible to override the property in a subclass and use it in the same way.

Returning reference to a singleton class instance within its functions

In the following code I would like to set a reference to the class instance so that static functions can return a reference to it:
open class TestRunner {
init {
instance = this
}
companion object {
private lateinit var instance: TestRunner
fun addTestSetups(vararg testSetups: () -> TestSetup): TestRunner {
for (setup in testSetups) {
testsSetups.add(setup)
}
return instance
}
}
}
But setting instance = this is not allowed. How can I return an instance of the class from a function while keeping the class as a singleton?
If I get you right, you want something like this:
abstract class TestRunner {
companion object : TestRunner()
}
This seems to work. Instead of keeping a variable that holds a reference to the class, simply referencing the name of the class is sufficient. However, to return an instance of the class from functions, the return type must be Companion:
open class TestRunner {
companion object {
fun addTestSetups(vararg testSetups: () -> TestSetup): Companion {
for (setup in testSetups) {
testsSetups.add(setup)
}
return TestRunner
}
}
}
This is not a true singleton because you can still create a new instance if you did this:
val testRunner = TestRunner()
However, if you never create an instance but only refer to the functions statically, it does behave like a singleton and the state of any private variables inside the companion object will still be maintained.
Update:
I came across this code on the Android developer site that shows an example of a class that is setup as a singleton:
class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
private val stockManager: StockManager = StockManager(symbol)
private val listener = { price: BigDecimal ->
value = price
}
override fun onActive() {
stockManager.requestPriceUpdates(listener)
}
override fun onInactive() {
stockManager.removeUpdates(listener)
}
companion object {
private lateinit var sInstance: StockLiveData
#MainThread
fun get(symbol: String): StockLiveData {
sInstance = if (::sInstance.isInitialized) sInstance else StockLiveData(symbol)
return sInstance
}
}
}
But it should be pointed out that this example requires functions that need to return an instance to first check if the instance variable is set and if not, create a new instance. I'm not sure what the point of that is since to call the function you already have an instance. So why bother create a new instance? Doesn't seem to make any sense.
object in Kotlin is the singleton, not the class its defined within. A companion object has the extra convenience of allowing you to call it by the name of that outer class. But it otherwise shares no hierarchy with it.
To make your class subclassable, you can't define the functions in the companion object. But you can make the class abstract so it can't be instantiated unless subclassed. Then make your companion object extend the abstract class so it will have all those functions available.
abstract class TestRunner{
open fun addTestSetups(vararg testSetups: () -> TestSetup): TestRunner{
//...
return this
}
companion object: TestRunner()
}
Usage:
TestRunner.addTestSetups(someTestSetup)
Note that your singleton is not an instance of TestRunner. It is a singleton instance of a subclass of TestRunner. But since you define no extra functions and override nothing, it behaves exactly like a TestRunner.
If you want a subclass:
abstract class ExtendedTestRunner: TestRunner() {
fun someOtherFunction() {}
companion object: ExtendedTestRunner()
}
The companions are not being subclassed, but their abstract parents can be.

OOP - How to create an interface in Reason

Let's say I have the following abstractProductA class with a public method called methodA :
class abstractProductA = {
pub methodA => "name";
};
I would like to create an interface that says function methodA should always return a string. Something similar to
interface abstractProductA {
abstractProductA(): string
}
only in reason, and then have class implement it. Any suggestions are more than welcome. Thank you
What you're really asking for it seems is how to define and use an abstract class, which is called a virtual class in OCaml/Reason:
class virtual virtualProductA = {
pub virtual methodA: string;
};
class abstractProductA = {
inherit virtualProductA;
pub methodA = "name";
};
An interface is more for consumers to abstract away an implementation, and while a virtual class can be used as an interface by itself, since OCaml/Reason objects are structurally typed you can also just specify the object type you need. And of course you can bind it to a name if you like:
type interfaceA = {.
methodA : string
};
let f (p: interfaceA) => Js.log p#methodA;
f (new abstractProductA);

Kotlin static methods and variables

I want to be able to save a class instance to a public static variable but I can't figure out how to do this in Kotlin.
class Foo {
public static Foo instance;
public Foo() {
instance = this;
}
}
Update: since this answer is getting a decent amount of upvotes, I really wanted to say that you shouldn't do the below, but instead just use object Foo { ... }, like Roman rightly points out in the comment.
Previous answer:
The closest thing to Java's static fields is a companion object. You can find the documentation reference for them here: https://kotlinlang.org/docs/reference/object-declarations.html#companion-objects
Your code in Kotlin would look something like this:
class Foo {
companion object {
lateinit var instance: Foo
}
init {
instance = this
}
}
If you want your fields/methods to be exposed as static to Java callers, you can apply the #JvmStatic annotation:
class Foo {
companion object {
#JvmStatic lateinit var instance: Foo
}
init {
instance = this
}
}
It looks that you want to define a singleton object. It is supported in Kotlin as a first-class concept:
object Foo {
...
}
All the boilerplate code with static field and constructor is taken care by the Kotlin automatically. You don't have to write any of that.
From the Kotlin code you can refer to the instance of this object simply as Foo. From the Java code you can referer to the instance of this object as Foo.INSTANCE, because the Kotlin compiler automatically creates the corresponding static field named INSTANCE.
first you create a simple class then after create a block followed by companion object keyword
for example:
class Test{
companion object{
fun getValue(): String{
return "Test String"
}
}
}
you can call this class function using class name dot function name
for example:
// here you will get the function value
Test.getValue()
You can create a companion object for the class, and if you want the field to be static you can use the annotation #JvmStatic. Companion object have access to private members of the class it is companion for.
See below an example:
class User {
private lateinit var name: String
override fun toString() = name
companion object {
#JvmStatic
val instance by lazy {
User().apply { name = "jtonic" }
}
}
}
class CompanionTest {
#Test
fun `test companion object`() {
User.instance.toString() shouldBe "jtonic"
}
}