Can I get parent class name ( first one) on inherit classes? - oop

At example I have three classes : View , FView ( extends View) and MView (extends View) . I have variable from type MView and want to to check it against parent class View ( i.e if this variable is from class View ). Is it possible to get the parent class ( View class) ? . Here is full example: https://try.haxe.org/#eA594
class Test {
static function main() {
var v = new SView();
trace(Type.getClassName( Type.getSuperClass(Type.getClass(v))) );
}
}
class View :
class View {
public function new() {
}
}
class FView :
class FView extends View {
public function new() {
super();
}
}
class SView :
class SView extends FView {
public function new() {
super();
}
}

If you want to get to the base class, you can simply recurse or iterate until Type.getSuperClass() returns null:
// at runtime: find out what is the base class of `v`
var base:Class<Dynamic> = Type.getClass(v);
while (true) {
var s = Type.getSuperClass(base);
if (s == null)
break;
base = s;
}
trace(Type.getClassName(base));
However, you mention that you want to do this simply to check if MView (or SView) are of the View type.
Well, for this, there are a few simpler alternatives...
First, at compile type, you can simply use a type check (or an assignment) to check if v:SView unifies with View:
// at compile time: enforce that `v` be of type `View` or compatible with it
var v1 = (v:View); // use a type check
var v2:View = v; // or simply pass it to something expecting `View`
If you need to do it at runtime, that's possible as well with Std.is():
// at runtime: check if `v` is a subclass instance of `View`
trace(Std.is(v, View));
For a complete example, check out this Try Haxe instance.

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 handle polymorphism in kotlin

I am working with an abstract class and two concrete ones, which implementing the abstract one. The diagram is as the next:
My classes looks as:
abstract class NavItem() {
var attributes: String = ""
var text = ""
}
class NavMenu(val items: MutableList<NavItem>) : NavItem()
class NavLink(var shortText: String) : NavItem()
The problem is when I try to work with the items which could be NavMenu or NavLinks, the NavMenus has a collection of NavLinks.
I am trying to work with the items using polymorphism as the next code:
navMenu.items.forEach{ item ->
buildNavItem(item)
}
the buildNavItem methods seems as:
private fun buildNavItem(navMenu: NavMenu){
navMenu.items
navMenu.attributes
navMenu.items
}
private fun buildNavItem(navItem: NavItem){
navItem.text
navItem.attributes
}
private fun buildNavItem(navLink: NavLink){
navLink.text
navLink.attributes
}
But the code is always getting into buildNavItem(navItem: NavItem), even when in the for each I can see sometimes that the item is NavLink, or is NavMenu.
Any suggestion?
Thanks!!
That is not how polymorphism works. You have navMenu.items list that is the type of MutableList<NavItem>, it can store NavItems or its descendants. In forEach function you go through each item, which has NavItem type, and call buildNavItem(item) function. In this case buildNavItem(navItem: NavItem) is always called. To call the same method with another parameter you need to explicitly cast it to that type. What I recommend, and that's how polymorphism works, is to create buildNavItem() function in NavItem class and implement it in descendants:
abstract class NavItem() {
var attributes: String = ""
var text = ""
abstract fun buildNavItem()
}
class NavMenu(val items: MutableList<NavItem>) : NavItem() {
override fun buildNavItem() {
// ... your concrete implementation for NavMenu
}
}
class NavLink(var shortText: String) : NavItem() {
override fun buildNavItem() {
// ... your concrete implementation for NavLink
}
}
And then you can call it in forEach function:
navMenu.items.forEach { item ->
item.buildNavItem()
}
In that case buildNavItem() function will be called for the right object, that is stored in navMenu.items, i.e. if it is an object of NavLink type then function 'buildNavItem()', overridden in NavLink class, will be called.
Problem:
navMenu.items.forEach { item ->
item.buildNavItem()
}
Since items is of type List<NavMenu>, the compiler will call the function which is appropriate for an item of type NavMenu, in this case the overload which takes a NavMenu.
Solution:
In order to call a more specific overload the compiler needs to know the type. You can smart cast the items an the appropriate function will be called:
private fun buildNavItem(navMenu: NavMenu) {
when(navMenu){
is NavItem -> buildNavItem(navMenu) // navMenu is smart casted to NavItem
is NavLink -> buildNavItem(navMenu) // navMenu is smart casted to NavLink
else -> throw IllegalStateException("Unknown subtype ${navMenu::class.simpleName} of NavMenu")
}
}
This way whenever you call buildNavItem, you delegate to the appropriate function.

Get companion class in companion object

Is there a way to get the javaClass of the companion class inside a companion object without knowing it's name?
I suppose I could get it by doing something like this:
open class TestClass {
companion object {
init {
val clazz = Class.forName(this::class.java.canonicalName.removeSuffix(".Companion"))
}
}
}
However, this does not work for class InheritingClass : TestClass(). It would still give me TestClass, not InheritingClass.
I was hoping for something more straightforward like this::class.companionClass.
Getting the class of the companion object of a given class will look like this:
TestClass::class.companionObject
Here's an example:
class TestClass {
companion object {
fun sayHello() = "Hello world"
}
}
If you want to get the class that contains the companion, since the latter is always an inner class of the former,
class TestClass {
companion object {
fun whichIsMyParentClass() = this::class.java.declaringClass // It'll return TestClass
}
}
And to further simplify, you'll also want to create an extension property:
import kotlin.reflect.KClass
val <T : Any> KClass<T>.companionClass get() =
if (isCompanion)
this.java.declaringClass
else
null
So, whenever you want to get the parent class of the companion object,
class TestClass {
companion object {
fun whichIsMyParentClass() = this::class.companionClass // It'll return TestClass
}
}
The companion class itself has no reference to the actual class as you can see in this bytecode
public final class TestClass$Companion {
private TestClass$Companion() { // <init> //()V
<localVar:index=0 , name=this , desc=LTestClass$Companion;, sig=null, start=L1, end=L2>
L1 {
aload0 // reference to self
invokespecial java/lang/Object <init>(()V);
return
}
L2 {
}
}
public TestClass$Companion(kotlin.jvm.internal.DefaultConstructorMarker arg0) { // <init> //(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
<localVar:index=0 , name=this , desc=LTestClass$Companion;, sig=null, start=L1, end=L2>
<localVar:index=1 , name=$constructor_marker , desc=Lkotlin/jvm/internal/DefaultConstructorMarker;, sig=null, start=L1, end=L2>
L1 {
aload0 // reference to self
invokespecial TestClass$Companion <init>(()V);
return
}
L2 {
}
}
}
The reference is only the other way around (see decompiled kotlin class)
public final class TestClass {
public static final Companion companion = ...
}
So you can either do it as you just did by cutting off the .Companion part of the class name or you reference it by hard with TestClass::class.java (what is in my opinion no problem and the best solution)
If you need to print the class name, you can add simpleName, such as
this::class.java.declaringClass.simpleName

Using class variables within an instance of a class

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.

OOP question involving the best way to reference a base class protected variable without having to typecast every-time it is used

I have a quick OOP question and would like to see how others would approach this particular situation. Here it goes:
Class A (base class) -> Class B (extends Class A)
Class C (base class) -> Class D (extends Class C)
Simple so far right? Now, Class A can receive an instance of Class C through its constructor. Likewise, Class B can receive an instance of either class C or Class D through its constructor. Here is a quick snippet of code:
Class A
{
protected var _data:C;
public function A( data:C )
{
_data = data;
}
}
Class B extends A
{
public function B( data:D )
{
super( data );
}
}
Class C
{
public var someVar:String; // Using public for example so I don't need to write an mutator or accessor
public function C() { } // empty constructor for example
}
Class D extends C
{
public var someVar2:String; // Using public for example so I don't need to write an mutator or accessor
public function D() { super(); } // empty constructor for example
}
So, let's say that I am using class B. Since _data was defined as a protected var in Class A as type C, I will need to typecast my _data variable to type D in class B every time I want to use it. I would really like to avoid this if possible. I'm sure there is a pattern for this, but don't know what it is. For now, i'm solving the problem by doing the following:
Class B extends A
{
private var _data2:D;
public function B( data:D )
{
super( data );
_data2 = data;
}
}
Now, in class B, I can use _data2 instead of typecasting _data to type D every-time I want to use it. I think there might be a cleaner solution that others have used. Thoughts?
I think B doesn't take C or D... in order for it to do what you wrote it should be
public function B( data:C )
{
super( data );
}
At least as far as I used to know :)
I doubt you can use a downwards inheritance in your case.
As for the pattern, the best one to use in situations like these is Polymorphism. Alternatively, depending on language, you can use interfaces. Or if languages allow it, even a combination of conventional code and templates.
Most modern OO languages support covariant of return type, that is: an overriding method can have a return type that is a subclass of the return type in the original (overridden) method.
Thus, the trick is to define a getter method in A that will return C, and then have B override it, such that it returns D. For this to work the variable _data is immutable: it is initialized at construction time, and from that point it does not change its value.
Class A {
private var _data:C;
public function A(data:C) {
_data = data;
}
public function getData() : C {
return _data;
}
// No function that takes a C value and assigns it to _data!
}
Class B extends A {
public function B(data:D) {
super(data);
}
public function getData() : D { // Override and change return type
return (D) super.getData(); // Downcast only once.
}
}
This how I usually write it in Java:
public class A {
private final C data;
public A(C data) { this.data = data; }
public C getData() { return data; }
}
public class B extends A {
public B(D data) { super(data); }
#Override
public D getData() { return (D) super.getData(); }
}