Discussion:
[dart-misc] factory constructor with template types
Peter StJ
2015-07-14 15:34:36 UTC
Permalink
I am trying to understand how to use factory constructor to return subtypes
where needed, but I keep getting it wrong.

The main idea is simple: have a base class that defines the interface and
use factory to return subtypes. If needed in user code check the exact
type, otherwise use as usual. The reason to want template in the base class
is to provide information about the type of value to be returned.

Example:

class A<T> {
final T value;
A.internal(this.value);

factory A(value) {
if (value is String) return new A.internal(value);
else return new B(1);
}
}


class B extends A<int> {
B(value): super.internal(value);
}

The problem is reported issue: Return type 'B' is not a 'A<T>' as defined
by method A.create;

I don't see how it is not, when it is extending it and providing specific
type for 'T'.

I am doing something wrong when it comes to templetizing the whole thing.

The usage code would have been to have 'is' checks for the exact type and
then decide what to do with the 'value'. The reason I do not use dynamic
for value is that it can be 3 'types' of 'String' (i.e. depending on
formatting) and comparing it at each use is tedious, instead I want to use
the factory to return exact subtype that the user code knows how to handle
(or skip if does not) and still receive 'String' as type for 'value'.
Another use is to have the 'A' extended with template type set to something
entirely different (example usage would be 'content -> value to be the
content of a html.Node - it could be String, Node or NodeList).

Can you direct me in the right direction?

Thanks!
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new

To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Günter Zöchbauer
2015-07-14 16:33:24 UTC
Permalink
I tried your code and it works fine without any error


main() {
var a = new A('a');
var b = new A(1);

print(a.value);
print(a.runtimeType);
print(b.value);
print(b.runtimeType);
}


prints

a
A
1
B
Post by Peter StJ
I am trying to understand how to use factory constructor to return
subtypes where needed, but I keep getting it wrong.
The main idea is simple: have a base class that defines the interface and
use factory to return subtypes. If needed in user code check the exact
type, otherwise use as usual. The reason to want template in the base class
is to provide information about the type of value to be returned.
class A<T> {
final T value;
A.internal(this.value);
factory A(value) {
if (value is String) return new A.internal(value);
else return new B(1);
}
}
class B extends A<int> {
B(value): super.internal(value);
}
The problem is reported issue: Return type 'B' is not a 'A<T>' as defined
by method A.create;
I don't see how it is not, when it is extending it and providing specific
type for 'T'.
I am doing something wrong when it comes to templetizing the whole thing.
The usage code would have been to have 'is' checks for the exact type and
then decide what to do with the 'value'. The reason I do not use dynamic
for value is that it can be 3 'types' of 'String' (i.e. depending on
formatting) and comparing it at each use is tedious, instead I want to use
the factory to return exact subtype that the user code knows how to handle
(or skip if does not) and still receive 'String' as type for 'value'.
Another use is to have the 'A' extended with template type set to something
entirely different (example usage would be 'content -> value to be the
content of a html.Node - it could be String, Node or NodeList).
Can you direct me in the right direction?
Thanks!
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new

To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Günter Zöchbauer
2015-07-14 16:33:58 UTC
Permalink
What Dart versions are you using?
Mine is Dart VM version:
1.12.0-edge.868d2c6c3e949a03c395efc2c3bfbe0761a295dc (Mon Jul 13 18:07:44
2015) on "linux_x64"
Post by Peter StJ
I am trying to understand how to use factory constructor to return
subtypes where needed, but I keep getting it wrong.
The main idea is simple: have a base class that defines the interface and
use factory to return subtypes. If needed in user code check the exact
type, otherwise use as usual. The reason to want template in the base class
is to provide information about the type of value to be returned.
class A<T> {
final T value;
A.internal(this.value);
factory A(value) {
if (value is String) return new A.internal(value);
else return new B(1);
}
}
class B extends A<int> {
B(value): super.internal(value);
}
The problem is reported issue: Return type 'B' is not a 'A<T>' as defined
by method A.create;
I don't see how it is not, when it is extending it and providing specific
type for 'T'.
I am doing something wrong when it comes to templetizing the whole thing.
The usage code would have been to have 'is' checks for the exact type and
then decide what to do with the 'value'. The reason I do not use dynamic
for value is that it can be 3 'types' of 'String' (i.e. depending on
formatting) and comparing it at each use is tedious, instead I want to use
the factory to return exact subtype that the user code knows how to handle
(or skip if does not) and still receive 'String' as type for 'value'.
Another use is to have the 'A' extended with template type set to something
entirely different (example usage would be 'content -> value to be the
content of a html.Node - it could be String, Node or NodeList).
Can you direct me in the right direction?
Thanks!
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new

To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Günter Zöchbauer
2015-07-14 16:40:10 UTC
Permalink
Sorry, I get the same error at
new B(1)
but I added the code to a big project and the analyzer took some time until
it showed the error.
But runs fine even in checked mode.
Might be a bug in the analyzer.
Post by Peter StJ
I am trying to understand how to use factory constructor to return
subtypes where needed, but I keep getting it wrong.
The main idea is simple: have a base class that defines the interface and
use factory to return subtypes. If needed in user code check the exact
type, otherwise use as usual. The reason to want template in the base class
is to provide information about the type of value to be returned.
class A<T> {
final T value;
A.internal(this.value);
factory A(value) {
if (value is String) return new A.internal(value);
else return new B(1);
}
}
class B extends A<int> {
B(value): super.internal(value);
}
The problem is reported issue: Return type 'B' is not a 'A<T>' as defined
by method A.create;
I don't see how it is not, when it is extending it and providing specific
type for 'T'.
I am doing something wrong when it comes to templetizing the whole thing.
The usage code would have been to have 'is' checks for the exact type and
then decide what to do with the 'value'. The reason I do not use dynamic
for value is that it can be 3 'types' of 'String' (i.e. depending on
formatting) and comparing it at each use is tedious, instead I want to use
the factory to return exact subtype that the user code knows how to handle
(or skip if does not) and still receive 'String' as type for 'value'.
Another use is to have the 'A' extended with template type set to something
entirely different (example usage would be 'content -> value to be the
content of a html.Node - it could be String, Node or NodeList).
Can you direct me in the right direction?
Thanks!
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new

To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Yissachar Radcliffe
2015-07-14 16:41:09 UTC
Permalink
You can just cast it to A<T> when you return it:

return new B(1) as A<T>;
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new

To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Peter StJ
2015-07-14 16:58:27 UTC
Permalink
This casting seems a bit off, after all I am trying to propagate the type
of 'value' as static type that is defined on the subclass and the
superclass it is template.

Maybe I misunderstand the template types at all.

If I skip the factory instantiate step and instead use the sub-classes
directly it works fine (Meaning that I get the exact type of 'value' wen
coming from subclass instance).

var b = new B(1);
var c = b.value; // <-- c is 'int'

Gunter: how can I verify is this is analyzer bug? I tested on 1.10 (still
hard-attached to darteditor) but as you confirmed it is the same in 1.12.

For now I use external function to get new A<int>(1) and then test with if
(instance is A<int>) instead for testing with exact subtype.
Post by Yissachar Radcliffe
return new B(1) as A<T>;
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new

To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Yissachar Radcliffe
2015-07-14 17:13:29 UTC
Permalink
I don't see how this is an analyzer bug.

Your factory method returns type A<T>. A<int> is not A<T> so within the
factory it gives you an error when you try to return B which is A<int>.

You happen to know in this case that T will be int and it will work out,
but the analyzer doesn't know this, hence why a cast is appropriate.
Post by Peter StJ
This casting seems a bit off, after all I am trying to propagate the type
of 'value' as static type that is defined on the subclass and the
superclass it is template.
Maybe I misunderstand the template types at all.
If I skip the factory instantiate step and instead use the sub-classes
directly it works fine (Meaning that I get the exact type of 'value' wen
coming from subclass instance).
var b = new B(1);
var c = b.value; // <-- c is 'int'
Gunter: how can I verify is this is analyzer bug? I tested on 1.10 (still
hard-attached to darteditor) but as you confirmed it is the same in 1.12.
For now I use external function to get new A<int>(1) and then test with if
(instance is A<int>) instead for testing with exact subtype.
Post by Yissachar Radcliffe
return new B(1) as A<T>;
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new

To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
'Bob Nystrom' via Dart Misc
2015-07-14 17:45:18 UTC
Permalink
Post by Yissachar Radcliffe
You happen to know in this case that T will be int and it will work out,
but the analyzer doesn't know this, hence why a cast is appropriate.
+1. If this was a trivia show, Yissachar would be proceeding to the next
round. :)

- bob
--
For other discussions, see https://groups.google.com/a/dartlang.org/

For HOWTO questions, visit http://stackoverflow.com/tags/dart

To file a bug report or feature request, go to http://www.dartbug.com/new

To unsubscribe from this group and stop receiving emails from it, send an email to misc+***@dartlang.org.
Loading...