class ClassA {}
class ClassB extends ClassA {}
class ClassC extends ClassA {}
and
ClassA p0 = new ClassA();
ClassB p1 = new ClassB();
ClassC p2 = new ClassC();
ClassA p3 = new ClassB();
ClassA p4 = new ClassC();
p0 = p1 works
But, p1 = p2 fails compilation....
Could not figure out why is this behavior when the hierarchy is same in both the statements? A --> B --> C
In your hierarchy A->B->C is not true. It is A->B, A->C. And C is not a subtype of B.
Related
I have a question. If ClassA aggregates ClassB and ClassC and ClassA calls a method of Class C in which it uses attributes from object of ClassB (passed by arguments) should I connect ClassB and ClassC or aggregation is enough?
Image for example:
Diagram UML
Implementation:
class ClassA {
constructor() {
this.stringA = "Hello"
this.objB = new ClassB();
this.objC = new ClassC();
}
functionA() {
this.objB.functionB(this.stringA);
this.objC.functionC(this.objB.intB);
}
}
class ClassC {
constructor() {}
functionC(intB) {
console.log(intB);
}
}
class ClassB {
constructor() {
this.intB = 10;
}
functionB(stringA) {
console.log(stringA);
}
}
Thanks for your help
In your diagram you use compositions, not 'just' aggregations, that means the instances of ClassB and ClassC will disappear when the instance of ClassA will disappear.
The goal of the compositions and aggregations is not to say a class calls a method of an other class or use one of its attribute.
If ClassB uses an attribute of ClassC (already strange, is it public ?) you can use a dependency, but if you add a dependency each time you take the risk to have a dependency between a lot of classes, and the goal of a class diagram is not really to indicate that
There is 2 classes:
A - base class
B - class of member of A
with implementation something like this:
class A {
val b : B = B()
}
class B
Problem
Is it possible to create a binding for b to hide redundant info about b source in common classes?
Kodein declaration:
override val kodein by Kodein.lazy {
bind<A>() with singleton { A() }
bind<B>() with "a.b some impl???"
}
Usecase
class Usecase(kodein : Kodein){
val b : B = kodein.instance()
}
Very simple :
bind<B>() with provider { instance<A>().b }
The provider binding is the simplest one : it will call the provided function everytime.
The function itself runs inside a Kodein context, hence the use of the instance function.
If a set of inner classes are the only implementations (subclasses) of their outer abstract containing class, how does one instantiate them?
abstract class A {
inner class A1 : A()
inner class A2 : A()
}
In other words, what is the syntax to construct an instance of A1 or A2?
EDIT: ... outside the body of class A.
Are you looking for this?
abstract class A {
fun doSome() { // OK
val a1 = A1()
val a2 = A2()
}
inner class A1 : A()
inner class A2 : A()
}
I think you probably want to construct instances of A1/A2 outside of A, like:
abstract class A {
inner class A1 : A()
inner class A2 : A()
}
fun doSome() { // Error
val a1 = A1()
val a2 = A2()
}
This is not allowed in both Kotlin and Java, because the inner class holds pointers to the outer class. If you want to construct A1/A2 outside of A, simply remove the inner modifiers.
abstract class A {
class A1 : A()
class A2 : A()
}
fun doSome() { // OK
val a1 = A.A1()
val a2 = A.A2()
}
Also, in addition, since you said it's
a set of inner classes are the only implementations (subclasses) of their outer abstract containing class
You can replace abstract modifier with sealed. This will help Kotlin do exhautiveness check in when expression.
I have a data class MyDataClass:
data class MyDataClass(val a: Int, val b: Int)
and a class MyClass with two properties. I want to destructure an instance of MyDataClass, so a and b are assigned to MyClass properties, instead of declare new variables:
class MyClass {
val a: Int
val b: Int
init {
val mdc = MyDataClass(1, 4)
(a, b) = mdc //error
}
}
No, destructuring declarations are only allowed for local variables and lambda parameters.
Also, they are only used to create multiple local variables at once. So val (a, b) = mdc is allowed, but
(a, b) = mdc is invalid syntax, even if a and b are not properties.
Although destructuring declaration are only allowed for local you can still do something like this
class MyClass {
val a: Int
val b: Int
init {
val (a, b) = MyDataClass(1, 4)
this.a = a
this.b = b
}
}
I was wondering, is it possible that a superclass to access the methods of a inherited subclass, like for example in Java?
I know that a subclass can override and even implements, in case of abstract classes, the methods of the superclass, but the question mentioned above is possible?
Thanks
Example in c#.. in superclass make abstract method, which is implemented in derived class
public abstract class SuperCLass
{
public void CallSubMethod()
{
Test(); // calls method in derived class
}
public abstract void Test();
}
public class SubClas : SuperCLass
{
public override void Test()
{
// code here
}
}
Java, PHP, Ruby, Python, C# (and so on) methods are always virtual, so, no matter what, when you override a method in a subclass, this version will be called:
public class SuperClass {
public void someMethod() {
otherMethod();
}
public void otherMethod() {
System.out.println("Super");
}
}
public class SubClass extends SuperClass {
public void otherMethod() {
System.out.println("Sub");
}
}
SubClass o1 = new SubClass();
o1.someMethod(); // Outputs: Sub
SuperClass o2 = new SubClass();
o2.someMethod(); // Also outputs: Sub
So, you not just CAN access your subclass method, you HAVE TO.
Just for comparison, in C++, for example, things work different. If you don't declare a method as virtual, you can't override it.
I' ll try to explain as they explained to me at university.
You have a reference:
Object o = new Object()
His static type(ST) is Object : this is his own type and never changes.
His dynamic type(DT) is also Object(in this case): the reference point to an object of type Object, but it can change.
for example if i write :
Object o = new String("abc") // now his ST == Object but the DT == String
That being said:
Upcasting is always permitted: consider two references s and r. the assignment s=r compile and execute always if ST(r) <= ST(s) (the static type of r is, in the hierarchi, less or equals to the static type of s)
for example:
class A { }
class B extends A { }
...
A a = new A(); B b = new B();
a = b // OK, upcast
Downcasting: at compile-time it is always legal to downcast from a type X to a type Y if X and Y belong to hierarchy.
Consider the reference s. I want to cast s to a type C, so if C <= TS(s) it will always compile if I do the cast as : C r = (C)s
for example:
class A { }
class B extends A { }
class C extends A { }
...
A a = new A(); B b = new B();
C c = new C();
...
b = c // ILLEGAL
b = (B)a // OK at compile-time but maybe at run-time it is not!
When we run our application if the downcast fails, Java raise an Exception.
Otherwise it success.
To downcast correctly:
consider a reference ref and we want to cast to a type C. So a downcast will success if DT(ref) <= C <= ST(ref) .
And the downcast will be obtained as: C ref2 = (C)ref
for example:
// I suggest to write the hierarchy in a piece of paper and
// try the rules before coding.
class A { }
class B extends A { }
class C extends A { }
class D extends B { }
...
A a = new A(); B b = new B();
C c = new C(); D d = new D();
A r = new B();
A s = new D();
a = b; // OK, upcast
a = d; // OK, upcast
/* b = c; */ // ILLEGAL
b = (B)r; // OK, downcast
d = (D)r; // downcast: it compiles, but fails at run-time
d = (D)s; // OK, downcast
/* b = s; */ // ILLEGAL
/* d = (D)c; */ // ILLEGAL
b = (B)s; // OK, downcast
b = (D)s; // OK, downcast
PS: please forgive if I made some mistake but I wrote a bit in a hurry.
In Java, It's not possible, and I think what you are asking would go against OOP.