19

I did the following test, but it doesn't work:

//main.dart
class Test
{
  static const   a = 10;
  final b = 20;
  final c = a+1;

}

//part.dart
part of 'main.dart';
class Test
{
  final d = a +1;   //<---undefined name 'a'
} 

I would like to split the class in flutter tutorial into multiple files. For example: _buildSuggestions in a separate file, _buildRow in a separate file, etc.

update:

my solution:

before:

//main.dart
class RandomWordsState extends State<RandomWords> {
{
    final _var1;
    final _var2;
    @override
    Widget build(BuildContext context) {
      ...
      body: _buildList(),
    );

    Widget _buildList() { ... }
    Widget _buildRow() { ... }
}

after:

//main.dart
import 'buildlist.dart';
class RandomWordsState extends State<RandomWords> {
{
    final var1;
    final var2;
    @override
    Widget build(BuildContext context) {
      ...
      body: buildList(this),
    );

}

//buildlist.dart
import 'main.dart';

  Widget buildList(RandomWordsState obj) {
     ... obj.var1 ...
  }
camino
  • 10,085
  • 20
  • 64
  • 115
  • 1
    You can just import other files if accesss to private members isn't an issue. Which part isn't answered by my answer or which part of what you want to accomplish does cause you troubles? – Günter Zöchbauer Apr 01 '18 at 15:13

3 Answers3

22

I am faced with same problem. My variant based on extensions:

page.dart

part 'section.dart';

class _PageState extends State<Page> {
    build(BuildContext context) {
        // ...
        _buildSection(context);
        // ...
    }
}

section.dart

part of 'page.dart';

extension Section on _PageState {
    _buildSection(BuildContext context) {
        // ...
    }
}
Nickolay Savchenko
  • 1,474
  • 16
  • 28
  • Wow, this looks like a cool way to use partial files (like C# visual Studio). Do you know if there is some information pro or against this practice? – adrianvintu May 24 '21 at 21:16
  • 2
    @adrianvintu iOS developers use in this way on swift. After compilation this is the same as one big class. – Nickolay Savchenko May 27 '21 at 15:43
  • 1
    As a Swift dev, this is exactly what I was looking for! The only new thing is having to declare the `part` inside the main `class` file and its associated `part of` in your `extension`. Thanks! – Clifton Labrum Jul 16 '22 at 22:45
  • Great solution! You will have to remove all other directives from section.dart, e.g. import directives, in case there are, as it was the case with my code. – Giorgio Barchiesi Aug 22 '23 at 20:48
15

Dart doesn't support partial classes. part and part of are to split a library into multiple files, not a class.

Private (identifiers starting with _) in Dart is per library which is usually a *.dart file.

main.dart

part 'part.dart';

class Test {
  /// When someone tries to create an instance of this class
  /// Create an instance of _Test instead
  factory Test() = _Test;

  /// private constructor that can only be accessed within the same library
  Test._(); 

  static const   a = 10;
  final b = 20;
  final c = a+1;
}

part.dart

part of 'main.dart';
class _Test extends Test {
  /// private constructor can only be called from within the same library
  /// Call the private constructor of the super class
  _Test() : super._();

  /// static members of other classes need to be prefixed with
  /// the class name, even when it is the super class
  final d = Test.a +1;   //<---undefined name 'a'
} 

A similar pattern is used in many code-generation scenarios in Dart like in

and many others.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • I got the following error in fultter: The return type '_Test' of the redirected constructor isn't assignable to 'Test'. The class 'Object' doesn't have a constructor named '_'. – camino Apr 01 '18 at 15:18
  • Sorry, I forgot to add `extends Test` - fixed – Günter Zöchbauer Apr 01 '18 at 15:19
  • 1
    Thanks, it works now! So if I want to split class Test into multiple file, just create multiple classes which extend from Test, right? – camino Apr 01 '18 at 15:22
  • It depends on why you want to split it. Above pattern is (as mentioned) used for code generation, where one file is hand-written and the other is generated automatically. For purely hand-written classes this shouldn't be necessary. If classes become too big you probably need specialize your classes mire. – Günter Zöchbauer Apr 01 '18 at 15:25
  • Is it possible to use `part` not in library as well? I had tried but w/o success. – BambinoUA Jan 07 '22 at 07:15
  • @BambinoUA sorry, but I don't understand what "use `part` not in library" means. Can you please elaborate what you try to accomplish? – Günter Zöchbauer Jan 07 '22 at 08:09
  • I mean in regular code of regular flutter project (template is "app" not "package", "module" or "plugin"). I tried to use it with `import`s but it looks like it is impossible. – BambinoUA Jan 07 '22 at 08:40
  • There is no difference in this regard between app, package, module, plugin, but I would need more information to guess what could be the issue. – Günter Zöchbauer Jan 07 '22 at 09:19
  • It looks like `part of` can be used only in files which does not contain `import` statements. `The part-of directive must be the only directive in a part. Try removing the other directives, or moving them to the library for which this is a part.` And then I don't understand when this practice used... – BambinoUA Jan 07 '22 at 09:49
  • Actually I had an idea to separate `AppState` classes depending of target platform but use only `single` class in the code ``` final appState = AppState(); ``` So when I type `AppState` only single file would be suggested instead of 3 ones if I would use conditional export. – BambinoUA Jan 07 '22 at 09:52
  • I'd suggest you create a new question. Usually using `part`/´part of` of is a bad idea, except for code generation (like built_value, and others) where there are no alternatives. Everything in `lib/src` is private by convention. If you don't want others to use something, do not export it from public files i(files in `lib/`) – Günter Zöchbauer Jan 07 '22 at 09:55
5

I just extend it with extension keyword like Swift.

// class_a.dart
class ClassA {}

// class_a+feature_a.dart
import 'class_a.dart';    

extension ClassA_FeatureA on ClassA {
  String separatedFeatureA() {
    // do your job here
  }
}

Please ignore the coding conventions, it's just a sample.

DragonCherry
  • 742
  • 7
  • 10