In many languages if you try to instantiate abstract class you get compile time error.
In Dart however, you get warning while compiling and a runtime exception AbstractClassInstantiationError.
Why is that? Can someone provide an example, where it's reasonable to compile such code?
Dart tries to allow you to run your program while you are developing it.
That is why many things that are compile time errors in other languages are compile-time warnings and runtime errors in Dart. This includes "x is Foo" where Foo doesn't exist, type-annotating with a non-existing types, and calling constructors of partial (abstract) classes.
In short: because it's not a problem that prevents the program from being compiled (unlike a syntax error that might mean the rest of the file is interpreted wrongly), so there is no reason to stop you from running the code. Only if you hit the branch that actually depends on the problem will your program be stopped.
It appears that the answer is factory constructor in abstract class:
abstract class Foo {
factory Foo() { // make Foo appear to be instantiable
return new Bar();
}
some(); // some abstract method
Foo.name() {} just a named constructor
}
class Bar extends Foo {
Bar():super.name(); // call named super constructor
some() {} // implement abstract method
}
main() {
print(new Foo()); // "instantiate" abstract Foo
}
Output:
Instance of 'Bar'
Asking 'where it's reasonable to compile such code?' in Dart isn't very meaningful because Dart is an interpreted language - there is no compilation stage. Dart editors will issue warnings if they think you are making a type error as they analyse your code on the fly.
Factory constructors can be used to provide a 'default' concrete implementation of an abstract class as you have done in your example. This is used quite widely in Dart. For instance, if you create a new Map object you actually get a LinkedHashMap object - see this question and answer.
In your example your are not instantiating an instance of Foo ('new Foo' does not appear anywhere), you are instantiating a `Bar'. This is because when a factory constructor is called a new instance of its class is not automatically instantiated.
Related
A common question, specifically since Dart 2, is if it is possible to require some or all generic type arguments on some or all types - for example List<int> instead of List or MyType<Foo> instead of MyType.
It's not always clear what the intention is though - i.e. is this a matter of style (you/your team likes to see the types), to prevent bugs (omitting type arguments seems to cause more bugs for you/your team), or as a matter of contract (your library expects a type argument).
For example, on dart-misc, a user writes:
Basically, if I have this:
abstract class Mixin<T> {}
I don't have to specify the type:
// Works class Cls extends Object with Mixin<int> {} // ...also works
class Cls extends Object with Mixin {}
Is there some way to make the second one not allowed?
Strictly speaking, yes, and no.
If you want to enforce that type arguments are always used in your own projects (instead of relying on type inference or defaults), you can use optional linter rules such as always_specify_types. Do note this rule violates the official Dart style guide's recommendation of AVOID redundant type arguments on generic invocations in many cases.
If you want to enforce that generic type arguments are always used when the default would be confusing - such as List implicitly meaning List<dynamic>, no such lint exists yet - though we plan on adding this as a mode of the analyzer: https://github.com/dart-lang/sdk/issues/33119.
Both of the above recommendations will help yourself, but if you are creating a library for others to use, you might be asking if you can require a type argument to use your class. For example, from above:
abstract class Mixin<T> {}
abstract class Class extends Object with Mixin {}
The first thing you could do is add a default bounds to T:
// If T is omitted/not inferred, it defaults to num, not dynamic.
abstract class Mixin<T extends num> {}
If you want to allow anything but want to make it difficult to use your class/mixin when T is dynamic you could choose a different default bound, for example Object, or even better I recommend void:
In practice, I use void to mean “anything and I don’t care about the elements”
abstract class Mixin<T extends void> {
T value;
}
class Class extends Mixin {}
void main() {
var c = Class();
// Compile-time error: 'oops' isn't defined for the class 'void'.
c.value.oops();
}
(You could also use Object for this purpose)
If this is a class under your control, you could add an assertion that prevents the class from being used in a way you don't support or expect. For example:
class AlwaysSpecifyType<T> {
AlwaysSpecifyType() {
assert(T != dynamic);
}
}
Finally, you could write a custom lint or tool to disallow certain generic type arguments from being omitted, but that is likely the most amount of work, and if any of the previous approaches work for you, I'd strongly recommend those!
Is it possible to apply a mixin to a class without the target class inheriting from any other class? For example, can I implement the following:
class User with Persistence {
// implementation
}
Most of your examples of Mixins in dart seem to be coupled with inheritance.
Thanks in advance!
You have to inherit from another class if you want to use a mixin. However, you can simply inherit from Object:
class User extends Object with Persistence {
// implementation
}
But really, you can just inherit from Persistence as well which will have the same effect:
class User extends Persistance {
// implementation
}
Gilad Bracha explains that the syntax is specifically designed this way:
I think it is important to understand the semantic model here. "with"
is the mixin application operator, and it takes two parameters: a
superclass and a mixin, and yields a class. Saying "with Foo" in
isolation makes as much sense as saying >> 2 (you could interpret both
as curried functions, but that is very far from Dart). When you write
"C extends S with M", you are specifying a superclass following the
extends keyword, just as you do when you write "C extends K" except
that the superclass is not specified via an identifier but via a mixin
application. So the superclass would be "S with M".
As Lasse points out, as practical matter it doesn't restrict you, but
having the syntax reflect the underlying structure is important.
I'm coming from C#/F#/Haskell so I'm trying to come up with solutions to programming problems I'm used to solving with types.
class A where T : new() in C#, this is mainly so I can do new T() somewhere. This creates a malformed type error in Dart. Is there a reasonably idiomatic way to solve this? Perhaps with factories?
I did some experiments with mixins, in the case of name conflicts for inherited mixin members, the last mixin wins. So for the following:
abstract class mixA { void foo(); }
abstract class mixB { void foo(); }
class C extends Object with mixA, mixB {}
new C().foo();
this would end up calling mixB.foo() whereas
class C extends Object with mixB, mixA {}
would end up calling mixA.foo()
Is there anyway to access the members of the hidden mixins?
Suppose I mix 2 mixins with a field of the same name. Does the subclass instance have 2 fields at runtime (just 1 is inaccessible) or is the object like a dictionary and there is only 1 slot for each name?
1 is not possible. You can't call new on a generic type (or variable for that matter). The most common workaround is to create a closure that allocates the object instead.
The answers for 2 fall out of the fact that Mixins can be seen as super-classes: A extends Object with B, C is basically equivalent to:
class B' extends Object { <copy over code inside B> }
class C' extends B' { <copy over code inside C> }
class D extends C' { ... }
With this in mind:
no. there is no way to access hidden super elements.
yes. you would end up with multiple fields.
Small note: the <copy over code inside X> part is not completely correct since that would change the library-scope. Code from mixin B is conceptually in the library the mixin is declared in.
Are there any plans to introduce attributes
for classes, methods, parameters of methods,
something like C# or Java attributes ?
[Test]
class SomeClass
{
[Test]
someMethod()
}
or
#Test
class SomeClass
{
#Test
someMethod(#Test int param)
}
For many frameworks it would be very useful
In dart, they are called metadata / annotation. The syntax is quite close to java. Here's a example :
#Test testMethod() {}
In Dart Specification you can read :
Metadata consists of a series of annotations, each of which begin with the character #, followed a constant expression that starts with an identifier. It is a compile time error if the expression is not one of the following:
A reference to a compile-time constant variable.
A call to a constant constructor.
[....]
Metadata can appear before a library, class, typedef, type parameter, constructor, factory, function, field, parameter, or variable declaration and before an import or export directive.
There're already some annotations predifined in dart:core. Particulary #override, #deprecated and #proxy.
Dart already has annotations, similar to Java in some ways, they're just not used in very many places yet, and they're not accessible from reflection yet either.
See this article: http://news.dartlang.org/2012/06/proposal-to-add-metadata-to-dart.html
Here's a brief introduction to the two metadata annotations currently available in the Dart meta library:
Dart Metadata is your friend.
This doesn't preclude you from using your own, but these are the two that have tooling integration with the Dart Editor.
I'm using Delphi Pro 6. Right now, the only way to know if a class is missing a base class abstract method is to wait for the IDE to emit a "constructing instance of {derived class} containing abstract method {base class.abstract method name}" warning or to wait for a runtime Abstract Error method when an attempt to call the missing method is made. The former isn't sufficient since it only finds warnings for those derived classes actually constructed in the current project. The latter is just plain painful.
It would be so much better if Delphi output a fatal warning for all classes that do not declare/implement a base class abstract method immediately. Does anyone know a way to set this up or a plug-in that does this?
Thanks.
I've found the simplest way to do this is to add a section in the unit initialization area using a conditional define that creates an instance of each class that you think shouldn't have any abstract methods:
{$IFDEF CheckAbstracts}
initialization
TSubclass1.Create(params);
TAbstractClass1.Create(params); // Gives constructing instance of {derived class} containing abstract method warning
{$ENDIF}
Compile with the CheckAbstracts conditional, and you will get warnings whenever you have an incompletely implemented class.
A class containing abstract methods is only dangerous if you instantiate the class, so Delphi's warning is spot-on. You only get the abstract-error run time exception if you ignored at least one "instantiating class with abstract methods".
It's valid to not implement these methods. You might intend to implement the abstract method in yet another subtype.
A later version of Delphi/Win32 (I don't remember which) introduced formal abstract classes, which make it clear when you do and do not intend to instantiate the type. If you're rigorous about using this, the feature you request would then make sense. But for D6 it is not clear.