Is there a way to have some sort of multiple inheritance in Dart? I can't use Mixins because the "base" class must then inherit from Object (in my case the "base" class needs to extend ChangeNotifier). Something like protocol oriented programming?
Example:
import 'package:flutter/material.dart';
class BaseModel extends ChangeNotifier {
bool _busy = false;
bool get busy => _busy;
void setBusy(bool value) {
_busy = value;
notifyListeners();
}
}
Because BaseModel extends ChangeNotifier, one can't say:
class A with BaseModel - wrong
You can mostly say class A extends BaseModel, but I am trying to avoid inheritance.
Related
I can't understand why this code doesn't compile.
In my intentions, the following snippet should declare a BaseGenericClass with no constraint on its argument, and a GenericClass deriving from BaseGenericClass with a constraint on type T telling the compiler to accept only classes derived from AbstractArgClass.
abstract class BaseGenericClass<T> {
final T _arg;
BaseGenericClass(this._arg);
}
class GenericClass<T extends AbstractArgClass> extends BaseGenericClass<T> {
GenericClass() : super(ArgClass());
}
abstract class AbstractArgClass {}
class ArgClass extends AbstractArgClass {}
ArgClass derives from AbstractArgClass, still lines 8 raises this error:
The argument type 'ArgClass' can't be assigned to parameter type 'T'
I think the compiler is correct here. ArgClass and AbstractArgClass in fact do not extend T, and I can't see a way to tell them that T is meant to be ArgClass.
It should work if you change it like this:
class GenericClass<T extends AbstractArgClass> extends BaseGenericClass<T> {
GenericClass(T t) : super(t);
}
You have to supply your instance of ArgClass to the constructor of GenericClass:
final g = GenericClass(ArgClass());
If you do not want to provide this from ouside, you can add a static function to make a new instance, like:
class GenericClass<T extends AbstractArgClass> extends BaseGenericClass<T> {
GenericClass._(T t) : super(t);
static GenericClass make() => GenericClass._(ArgClass());
}
and get an instance:
final g = GenericClass.make();
Ber's answer apparently works around the problem introducing a sort of intermediation... I tried to create a useless IntermediateClass that just introduces the restrictions on the type T (T has to derive from AbstractArgClass). This works!!!
AnotherGenericClass, as expected, does not compile because AnotherClass does not extend AbstractArgClass.
Still the question: why?
It looks like a compiler glitch to me, do you agree?
abstract class BaseGenericClass<T> {
final T _arg;
BaseGenericClass(this._arg);
}
class IntermediateClass<T extends AbstractArgClass> extends BaseGenericClass<T> {
IntermediateClass(T arg) : super(arg);
}
class GenericClass extends IntermediateClass {
GenericClass() : super(ArgClass());
}
abstract class AbstractArgClass {}
class ArgClass extends AbstractArgClass {}
class AnotherClass {}
class AnotherGenericClass extends IntermediateClass {
AnotherGenericClass() : super(AnotherClass());
}
I am writing an app which deals with both cryptos and stocks. Because they share many common characteristics such as symbol, price, name etc, I created a base class 'instrument' then subclasses for stock and crypto. I have a generic 'manager' class for both, as loading, saving etc are again very similar. However, there are some functions, such as fetching a current price, that need to be implemented differently, so I have extended my generic manager class and I am trying to override the relevant function, i.e. fetchCurrentPrice() in the example below. Dart complains that
'CryptoManager.fetchCurrentPrice' ('Future Function(Crypto)') isn't a valid override of 'Manager.fetchCurrentPrice' ('Future Function(Instrument)').
I don't understand this, as I have defined as type in the manager, and Crypto extends Instrument, so I am fulfilling this criterion. Any idea where I am going wrong?
abstract class Instrument {
String name = 'Instrument';
double currentPrice = 0.0;
Instrument(this.name);
}
class Crypto extends Instrument {
Crypto(super.name);
String contractAddress = '0xBCCFF3FF6...';
}
abstract class Manager<T extends Instrument> {
List<T> instruments = [];
Future<double> fetchCurrentPrice(T instrument) async {
print('Fetching price for generic instrument');
return 12.80;
}
}
class CryptoManager extends Manager {
// this is causing the issue
#override
Future<double> fetchCurrentPrice(Crypto instrument) async {
print('Fetching price for crypto');
return 12.80;
}
}
void main(List<String> args) {
CryptoManager cryptoManager = CryptoManager();
var btcCrypto = Crypto('BTC');
cryptoManager.fetchCurrentPrice(btcCrypto);
}
Your class CryptoManager needs to extend Manager<Crypto>, not just "some Manager, kinda".
class CryptoManager extends Manager<Crypto>
How can I have an abstract private method in dart?
// person.dart
abstract class Person{
void _walk(); //Abstract Method
void _talk(); //Abstract Method
}
// jay.dart
import "person.dart";
class Jay extends Person{
#override
void _walk() {
print("Jay can walk");
}
#override
void _talk() {
print("Jay can talk");
}
}
I want to hide _walk and _talk from Jay instance
package:meta provides a #visibleForOverriding annotation that might do what you want. Note that violating it will generate only an analysis warning, and it won't be enforced at runtime.
Personally I think that putting things that are meant to be private in the abstract base class is a bad idea since they shouldn't be part of the interface. Consider instead doing:
abstract class Person {
...
}
abstract class _Person extends Person {
void walk();
void talk();
}
and now your library can internally derive classes from _Person and use walk and talk, and they won't be exposed at all to external consumers of your library.
I have a navigation bar that leads me to the class "Busca". A second class "_BuscaSatet" already extends "Busca".
How can i make 2 classes to extend "Busca" as i created a third one "Categorias"
I am new to dart, tried doing this:
class Busca extends StatefulWidget {
#override
_BuscaState createState() => _BuscaState();
_CategoriaState createState() => _CategoriaState();
}
and then
class _CategoriaState extends State<Busca> {
If you're looking to provide "generic" return types for a single method, you might try the following, which allows you to specify the intended return type with generics on the function level rather than at the class level:
class MyClass {
T createState<T>(...) {
...
return T(...);
}
}
Then you might call it as
MyClass myClass = MyClass();
OtherClass other = myClass.createState<OtherClass>(...);
I have a class I want to use mostly as a base class for other classes that have constant instances, but also as a mixin class for others. Ideally, I'm after something like the following:
class Base{
someMethod(){
//do something
}
}
class ConstantClass extends Base{
const ConstantClass();
anotherMethod(){
//do something else
}
}
class MixedClass extends NonMixinClass with Base{
thirdMethod(){
//a third thing
}
}
The above has an error in that ConstantClass cannot have a constant constructor without calling a super-class constant constructor. However, if I add a constructor of any kind to Base(), it can't be used as a mixin.
My current workaround is to duplicate functionality in static methods, as in the following:
class Base{
const Base();
static someStaticMethod(Base base){
//do something
}
someMethod() => Base.someStaticMethod(this);
}
class ConstantClass extends Base{
const ConstantClass(): super();
anotherMethod(){
//do something else
}
}
class BaseMixin implements Base{
someMethod() => Base.someStaticMethod(this);
}
class MixedClass extends NonMixinClass with BaseMixin{
thirdMethod(){
//a third thing
}
}
This isn't too bad when there's only one function in the base class, but things get pretty verbose for a complex class, and if there's a simple way of getting around the problem I'd love to keep things clean. Thanks in advance.
I though class ConstantClass extends Object with Base { would do it, but the new error I get is "Constant constructor cannot be declared for a class with a mixin". So I don't see a solution here, but not using a const constructor.