4

basend this Question I created an enum in dart with an extension methode:

enum TagVisibility {
  public,
  shared,
  private,
}

extension on TagVisibility {
  String get german {
    switch(this){
      case TagVisibility.public: return "Für alle sichtbar";
      case TagVisibility.shared: return "Für alle mit demselben Tag sichtbar";
      case TagVisibility.private: return "Nur für mich sichtbar";
      default: throw Exception("enum has more cases");
    }
  }
}

But I get the error Error: The method 'german' isn't defined for the class 'TagVisibility'. when I try to call this extension method:

import 'package:prototype/models/visibility.dart';
...
 DropdownButton<TagVisibility>(
          hint: Text("Wähle die Sichtbarkeit für diesen Tag"),
          value: _visibility ?? _visibilityDefault,
          onChanged: (visibility) {
            setState(() {
              _visibility = visibility;
            });
          },
          // items: List<DropdownMenuItem<TagVisibility>>(
          items: TagVisibility.values.map((visibility) => DropdownMenuItem(
            value: visibility,
            child: Text('${visibility.german()}'), // doesn't work
            // child: Text('${visibility.toString()}'), // works, but I want the custom messages.
          ),
          ).toList(),
        ),

I have absolutly no idea what I did wrong here. Can you please explain me how I can get this working? Thx!

DarkMath
  • 1,089
  • 2
  • 15
  • 29

5 Answers5

5

I found the solution here: Import extension method from another file in Dart

There are two ways:

Solution number 1: Place the extension method in the dart file where it is used. But often it is better the place the extension method in the same file as the correspondig enumeration. So I prefer this:

Solution number 2: Give the extension a name which is different from the enum name. Code:

enum TagVisibility {
  public,
  shared,
  private,
}

extension TagGerman on TagVisibility {
  String get german {
    switch(this){
      case TagVisibility.public: return "Für alle sichtbar";
      case TagVisibility.shared: return "Für alle mit demselben Tag sichtbar";
      case TagVisibility.private: return "Nur für mich sichtbar";
      default: throw Exception("enum has more cases");
    }
  }
}
DarkMath
  • 1,089
  • 2
  • 15
  • 29
  • 1
    I am happy you found sollution but technically this answer does not answers or resolves issue described in actual question of this post, which was: "Error: The method 'german' isn't defined for the class 'TagVisibility'.". It rather resolves issue of incorrect importing extensions. So I suggest you either change original post description (which is not fair), or post different question with different issue. This is needed just not to confuse other people reading your original post and possible solution. – Alex Radzishevsky Mar 22 '20 at 15:29
  • 1
    Naming the extension actually *is* the correct solution to the extension member `german` not being available in the library importing the enum and extension, and it solves the problem. – lrn Mar 23 '20 at 08:51
4

You need to give the extension a name.

Dart extensions can be declared without a name, but that just means they are given a fresh private name instead, and therefore the extension is only accessible inside the library where it is declared. You basically never want an extension without a name.

If you give it a public name, then the extension can be imported into other libraries along with the enum.

lrn
  • 64,680
  • 7
  • 105
  • 121
4

With Dart 2.17, you need not use extensions. You can simply place your methods in the enum. For example:

enum TagVisibility {
  public,
  shared,
  private;

String get german {
    switch(this){
      case public: return "...";
      case shared: return "...";
      case private: return "...";
    }
  }
}
CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
0

You defined as getter:

...
String get german {
...

but using it as method:

...
child: Text('${visibility.german()}'), // doesn't work
...

What you should do is to use it as getter:

...
child: Text('${visibility.german}'), // this should work
...
Alex Radzishevsky
  • 3,416
  • 2
  • 14
  • 25
  • Oh right. I tried this before and got the error `error: The getter 'german' isn't defined for the class 'TagVisibility'. (undefined_getter at [prototype] lib\gui\screens\register\6_register_list_of_interests.dart:70)` – DarkMath Mar 22 '20 at 14:19
  • This was most likely caused by fact that source of extension was not imported in library where you used it. It would be more helpful to see who source code with exact files and imports to help you better. – Alex Radzishevsky Mar 22 '20 at 14:34
  • The `visibility.dart` file has no imports. The imports of the other file are ```dart import 'package:flutter/material.dart'; // local file imports import 'package:prototype/gui/corporate_design.dart'; import 'package:prototype/controller/IController.dart'; import 'package:prototype/controller/controller.dart'; import 'package:prototype/controller/routes.dart'; import 'package:prototype/models/Tag.dart'; import 'package:prototype/models/visibility.dart'; ``` But only the one given in the question is relevant I think. – DarkMath Mar 22 '20 at 14:50
  • Why it doesn't make line breaks in comments in the code? -.- – DarkMath Mar 22 '20 at 14:52
0

Another approach

enum TagVisibility {
  public,
  shared,
  private,
}

extension TagGerman on TagVisibility {
  String get german {
     var values= ["Für alle sichtbar",
                  "Für alle mit demselben Tag sichtbar",
                  "Nur für mich sichtbar"];
      return values.elementAt(index);
    }
  }
}

ALWAYS add import '.../your_file.dart' every where you will use it

Don't forget to test!!! Take care with RangeError exception if you add more enum items

 group('Tag Visibility German', () {

    test('public german should be Für alle sichtbar', () {
      expect('Für alle sichtbar', TagVisibility.public.german());
    });
     ...

  });
Álvaro Menezes
  • 1,658
  • 1
  • 13
  • 14