Override final properties in abstract class Dart

4,283

Solution 1

  1. An abstract class can't be constructed by itself, but it can still have a constructor that derived classes can call. The constructor in the abstract base class can initialize its final members.

  2. Data members implicitly add getters and setters to the interface. final members implicitly add getters without a setter. This means that your classes could be:

    abstract class BusinessCard {
      CardView get cardView;
      CardInfo get cardInfo;
      Widget front(BuildContext context);
      Widget back(BuildContext context);
    }
    
    class Card1 extends StatelessWidget implements BusinessCard {
      @override
      final CardView cardView;
    
      @override
      final CardInfo cardInfo;
    
      Card1({
        required this.cardView,
        required this.cardInfo,
      });
      ...
    

    and now your abstract class would be a pure interface class with no implementation and that stores no data.

Solution 2

final variables cannot be reassigned, it has a final value so try to remove it .. and in implementing abstract class you don't need to add final variables because this class is treated like a template or general case that you want to reuse it inside your app.

so instead of using final class members, you use an abstract getter and setter.

you can also read this comment in a similar issue posted on in dart sdk Github repo: https://github.com/dart-lang/sdk/issues/28555

Solution 3

I would suggest:

abstract class BusinessCard extends StatelessWidget {
  BusinessCard({
    this.cardView, 
    this.cardInfo,
  });

  final CardView cardView;
  final CardInfo cardInfo;

  Widget front(BuildContext context);
  Widget back(BuildContext context);
}
class Card1 extends BusinessCard {
  Card1({
    @required CardView cardView,
    @required CardInfo cardInfo,
  }) : super(
          cardView: cardView,
          cardInfo: cardInfo,
        );

  @override
  Widget build(BuildContext context) {
    return cardView == CardView.front ? front(context) : back(context);
  }

  @override
  Widget front(BuildContext context) {}

  @override
  Widget back(BuildContext context) {}
}

Solution 4

You can always ignore immutable (but careful) with this line

// ignore: must_be_immutable

so your abstract class is

abstract class BusinessCard {
  CardView cardView;
  CardInfo cardInfo;
  Widget front(BuildContext context);
  Widget back(BuildContext context);
}

and your stateless widget

// ignore: must_be_immutable
class Card1 extends StatelessWidget implements BusinessCard {
  CardView cardView;
  CardInfo cardInfo;

  Card1({
    @required this.cardView,
    @required this.cardInfo,
  });

  @override
  Widget build(BuildContext context) {
    return cardView == CardView.front ? front(context) : back(context);
  }

  @override
  Widget front(BuildContext context) {

  }

  @override
  Widget back(BuildContext context) {
    
  }
}
Share:
4,283
developerjamiu
Author by

developerjamiu

Updated on December 24, 2022

Comments

  • developerjamiu
    developerjamiu over 1 year

    I created a Abstract Class with methods and properties that a Stateless Widget can override but after implementing the class, due to Stateless Widget immutability, I had to make the widget properties final and in turn make the Abstract class properties final as well. Then, I got error that the final variable must be initialized.

    What is the proper way to implement an Abstract Class with final variables?

    Abstract Class

    abstract class BusinessCard {
      final CardView cardView;
      final CardInfo cardInfo;
      Widget front(BuildContext context);
      Widget back(BuildContext context);
    }
    

    Implementing Class

    class Card1 extends StatelessWidget implements BusinessCard {
      final CardView cardView;
      final CardInfo cardInfo;
    
      Card1({
        @required this.cardView,
        @required this.cardInfo,
      });
    
      @override
      Widget build(BuildContext context) {
        return cardView == CardView.front ? front(context) : back(context);
      }
    
      @override
      Widget front(BuildContext context) {
    
      }
    
      @override
      Widget back(BuildContext context) {
        
      }
    }