Unable to use instance variable of a mixin in enhanced enum - dart

Minimum reproducible code:
// Compile error: Mixins applied to enums can't have instance variables
enum Os with Foo{
symbian(false),
android(true);
final bool smartphone;
const Os(this.smartphone);
}
This is my mixin:
mixin Foo {
final int x = 0;
}
Enhanced enum docs says:
Instance variables must be final, including those added by mixins.
But if my mixin has an instance variable, I am unable to use it in my enhanced enum. I am getting compile time error.

Related

Adding the generic type to a comparable type in Dart

This is a followup question after reading this Q&A:
Generic Sorting function accepts T, but want to ensure T is comparable
I have a class like so:
class BinarySearchTree<E extends Comparable> { ... }
so I can create an instance like this:
final tree = BinarySearchTree<int>();
My question is about using Comparable vs Comparable<E>. When I do this:
class BinarySearchTree<E extends Comparable> { ... }
then the type defaults to E extends Comparable<dynamic>. I normally try to avoid dynamic, so in order to be more explicit about the type that is being compared, it seems like I should write it this:
class BinarySearchTree<E extends Comparable<E>> { ... }
But in that case I get an error here:
final tree = BinarySearchTree<int>();
// 'int' doesn't conform to the bound 'Comparable<int>' of the type parameter 'E'.
// Try using a type that is or is a subclass of 'Comparable<int>'.
This demonstrates my lack of understanding of generics. What am I missing?
In Dart, a class cannot implement 2 different concrete instances of a generic interface:
abstract class Foo<T> {}
// error: Foo can only be implemented once
class Bar implements Foo<String>, Foo<int> {}
num implements Comparable<num>, because it would be slightly absurd for the built-in number types to not be comparable. However, since int is a subtype of num (and therefore inherits Comparable<num>, it cannot have Comparable<int>.
This leads to the slightly weird consequence that int does not implement Comparable<int>.
The problem you're facing is that from the language's point of view, there are 2 types involved: the type of the elements being compared, and the type of the elements they are being compared to.
As such, your type will need 2 type parameters:
class Tree<T extends Comparable<S>, S> {
T get foo;
}
final intTree = Tree<int, num>();
final foo = intTree.foo; // returns an int
Admittedly, this isn't a super clean solution, but if you're using Dart 2.13 or higher, you can use typedefs to make it a bit nicer:
typedef IntTree = Tree<int, num>;
typedef RegularTree<T> = Tree<T, T>;
final intTree = IntTree();
final stringTree = RegularTree<String>();
intTree.foo // is an int
stringTree.foo // is a String
There is another option, which is to just drop some type safety and use Comparable<dynamic>, but personally I'd recommend against it. BTW, if you want to avoid accidentally missing type parameters you can disable implicit-dynamic as described here: https://dart.dev/guides/language/analysis-options#enabling-additional-type-checks
This will give an error any time the type dynamic is inferred from context without the programmer actually typing the word dynamic

Dart Mixin get super field value

Based on a class and a mixin
class CounterModel extends MVAModel with CounterModelGeneratedCode {
int counter = 2;
}
mixin CounterModelGeneratedCode on MVAModel {
int get counter => store.get("counter", () => (super as CounterModel).counter);
set counter(int value) => store.set("counter", value);
}
The dart analyzer does not complain but on compilation I get an
Error: Can't use 'super' as an expression. To delegate a constructor
to a super constructor, put the super call as an initializer.
How can I access the overshadowed values of the CounterModel class (e.g. 2 for counter)?
You cannot do that, and the analyzer should have caught the syntax error too.
You cannot override the resolution of super-invocations, you can only call the actual superclass member.
Also, the counter is not on the superclass, which is MVAModel, so using super is not the right approach.
You could try (this as CounterModel).counter, which would work, but it isn't optimal. The cast is not necessary, we can do better.
What you probably want in this case is to add a definition of the counter variable to the mixin declaration:
abstract int counter;
That way, it requires classes mixing it in to define such a counter (which the one class doing so then does).
Then you can invoke the counter in the mixin as just this.counter.

Should subclasses inherit private mixin variables in Dart?

Should I get the following error:
class.dart:11:11: Error: The getter '_privateID' isn't defined for the class 'Y'.
- 'Y' is from 'class.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named '_privateID'.
From the following code?
mixin.dart:
class Mixin {
static int _nextID = 0;
int publicID = _nextID++; // I only need one of these lines
int _privateID = _nextID++; // but this variable is inaccessible
}
class.dart:
import 'mixin.dart';
class X with Mixin {
void run() {
print(publicID); // no error here
}
}
class Y with Mixin {
void run() {
print(_privateID); // Error: _privateID not defined
}
}
void main() {
Y().run();
}
Or is this a bug? If it's not a bug, I'd like to understand why this behavior is reasonable.
When I instead define the mixin in the same file as the above classes, I get no error.
(Dart SDK 2.4.1.)
It is not a bug.
The private field is inherited, but you cannot access it because its name is private to a different library.
Dart's notion of "privacy" is library private names.
The name _privateID in the mixin.dart library introduces a library private name. This name is special in that it can only be written inside the same library.
If someone writes _privateID in a different library, it is a different name, one unique to that library instead.
It is as if private names includes the library URI of the library it is written in, so what you really declare is a name _privateID#mixin.dart.
When you try to read that field in class.dart, you write ._privateID, but because it is in a different library, what you really write is ._privateID#class.dart, a completely different name, and the classs does not have any declarations with that name.
So, if one class needs to access a private member of another class (or mixin, or anything), then the two needs to be declared in the same library, because otherwise they cannot even write the name of that variable.
That is why the code works if you write the mixin in the same library.
If you want to move the mixin to a separate file, but not necessarily a separate library, you can use a part file.

Type name does not allow storage class to be specified?

Here is code in log.h file :
struct SUCC_CODE{
static const int RECOGNIZER_OK = 0;
};
The above piece of code in log.h file throwing compiler error:
Type name does not allow storage class to be specified
Struct members may not be static. Remove that specifier, and the compiler should stop complaining. This question explains that it is a valid specifier in C++.
C doesn’t allow you to use static within a struct. It’s not even clear what that would mean in a C struct.

Global variable in a module not accessible after the module being imported

I found that in the Rascal console, after I import a module which contains global variable definitions, these global variables are not accessible. Only global function names are accessible. For example, in the following code, after I import Foo in the console, I can call x() to get 1, but dereference x gives me an unbound variable error. Why?
module Foo
int x = 1;
int x() = 1;
Globals are default private in Rascal, to prevent you from easily doing such nastiness :-)
module Foo
public int x = 1;
int x() = 1;
This is a bit inconsistent, since the function is public by default but not when you consider that we will eventually remove globals from the language :-)

Resources