Maybe this is not a Dart specific question.
I have :
class A {
int a;
A(this.a);
}
class B extends A {
String b;
B(a, this.b) : super(a);
}
So you see, class A has an attribute int a and B just extends A and has an extra attribute String b and a wrapper class C :
class C {
A c;
C(this.c);
void doSomething() {
if (c is B) {
print(c.b);
} else {
print(c.a);
}
}
}
The Dart Editor complaints that the c doesn't have a getter b. How do you deal with this? I want to get rid the warning, but I don't want to add attribute b to class A
(c as B) works, but will do a dynamic type check (which will probably be eliminated by the VM).
If you just want to remove the warning, without changing the semantics of the program you can assign to a temporary variable of the correct type:
void doSomething() {
if (c is B) {
B b = c;
print(b.b);
} else {
print(c.a);
}
}
The analyzer shouldn't add a warning here. I think it's related to this issue : Analyzer fails to respect certain "is" checks.
In the meanwhile, you can use (c as B).b to cast c in B.
You can cast expression.
print((c as B).b);
Related
class AImpl : A {
override fun createB(): B {
return object : BImpl {
val t = this
override fun createC(): C {
return CBuilderInstance.buildC { // this: CBuilder
this.B = t // type: B
// How can I use 'this#Something' to replace the t.
}
}
}
}
}
class CBuilder {
fun buildC(block: CBuilder.() -> Unit): C {
...
}
}
Sorry that I cannot describe the problem I met.
What can I do to replace "t" in the code?
The IDE give me 2 suggestions, "this" and "this#AImpl", which is not working for this.
According to Kotlin Language Specification - This-expressions, a labeled this-expression can have the following forms:
this#type
this#function
this#lambda
this#outerFunction
The last 3 forms refer to the implicit receiver of functions/lambdas, which is obviously not what you want. You want to refer to the object created by the object literal object : BImpl { ... }.
The spec says (emphasis mine):
this#type, where type is a name of any classifier currently being declared (that is, this-expression is located in the inner scope of the classifier declaration), refers to the implicit object of the type being declared;
And also in Classifier Declarations, it says,
Important: object literals are similar to object declarations and are considered to be anonymous classifier declarations, despite being expressions.
So although object literals are classifier declarations, they do not have a name that we can write after the #.
To conclude, you cannot use a labeled this expression here, without also changing something else.
You can, for example, declare a local class, which has a name:
class AImpl : A {
override fun createB(): B {
class Foo : BImpl {
override fun createC(): C {
return CBuilder.buildC {
this.B = this#Foo
}
}
}
return Foo()
}
}
I don't get what is the actual use of generics in typescirpt.
interface ICustomer
{
name: string;
age: number;
}
function CalcAverageAge<c extends ICustomer>(cust1: c, cust2: c): number
{
return (cust1.age + cust2.age)/2;
}
resNumber = CalcAverageCustomerAge({name: "Peter", age: 62},
{name: "Jason", age: 33});
In the above example we are passing interface c to function CalcAverageAge.
But without using extends ICustomer we can't use age and name inside that class.
Then what is the use of passing template( c ) in the function.
We can directly write the code in below format
function CalcAverageAge(cust1: ICustomer, cust2: ICustomer): number
{
return (cust1.age + cust2.age)/2;
}
Can you give a real example where generics is really useful?
I will explain you my scenario where I need to use generics.
interface t1{
a:String
b:number
}
interface t2 {
a:String
b:number
c:number
}
interface t3 {
a:String
b:number
d:number
}
class base<T extends t1> {
constructor( input : T, type:string ){
//some common code for both derived1 and derived2
if(type==="derived1"){
console.log(input.c);// will throw error because t1 doesn't contains c
} else if ( type==="derived2"){
console.log(input.d);// will throw error because t1 doesn't contains d
}
}
}
class derived1 extends<t2>{
constructor(){
var temp = {a:"11",b:2,c:3}
super(temp,"derived1");
}
class derived2 extends<t3>{
constructor(){
var temp = {a:"11",b:2,d:3}
super(temp,"derived2");
}
}
Can we achieve this with generice?
If not what would be the best way of implementation avoiding duplicate codes.
In your example it is correct that the interface is all you need.
Generics is something that is useful when you want to make something generic; sometimes it might be so generic that you do not even need an interface. The example you bring up is not only a generic, it also limits what the generic can look like with an interface.
Other examples of what a generic can be used for is a collection that can contain any type of item. The array type in typescript is an example of that - var a = new Array<number>() - for example.
But say that you want to create a function that compares two items, something like this:
interface IValue { value: number; }
function max(a: IValue, b: IValue): IValue {
return a.value > b.value ? a : b;
}
In this case you have the issue that the max function returns its result as an IValue In most cases this is not what you want. What you want is something like this:
interface IValue { value: number; }
function max<T extends IValue>(a: T, b: T): T {
return a.value > b.value ? a : b;
}
Here the return type of max is whatever the generic type T is, and this is more useful.
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.
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(); }
}
For example, if you have class A, class B inheriting A, and class C inheriting B, is there any programming language in which class C can override a method of class A, even if class B don't override it?
class A {
method() {}
}
class B extends A{
}
class C extends B {
//override method from A
method(){}
}
AFAIK you can do this in most (if not all) OO languages, e.g. in Java and C++ for sure.
yes , It is very general case, Java does it.
This ruby code does exactly what you want:
class A
def hello
puts "hello from class A"
end
end
class B < A
end
class C < B
def hello
puts "hello from C"
end
end
B.new.hello
C.new.hello
Once executed you will have the following output:
hello from class A
hello from C
C# for one
public class A
{
virtual public int retval(int x)
{
return x;
}
}
public class B : A
{
}
public class C : B
{
public override int retval(int x)
{
return 3;
}
}
class Program
{
static void Main(string[] args)
{
A a = new C();
Console.WriteLine(a.retval(2).ToString());
}
}
I think most common languages will allow that without difficulty if all modules are recompiled. There is a gotcha in some (including C# and vb.net) if an override is added to a mid-level class which didn't have one when a child method was compiled. In that scenario, if the child classes are not recompiled, calls to their parent methods may bypass the mid-level classes (since those mid-level classes didn't have overrides when the child passes were compiled).