Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dart: switch case of a class?

Hello Guys, I hope you are doing well!

I got a question, it's how to use switch case on a class? (Here the 'state' is the main class, and other classes are inherited from state.)

like for example, I tried to replace this:

if(state is LoadingPage)        {return LoadingPage;}
else if {state is SuccessPage)  {return SuccessPage;}
else if {state is FailPage)     {return FailPage;}

to this:

switch (state){
case LoadingPage:   {return LoadingPage;}
case SuccessPage:   {return SuccessPage;}
case FailPage:      {return FailPage;}
}

It didn't work, what worked for me is making the state as a string, like this:

switch (state.toString()){
    case 'LoadingPage':      {return LoadingPage;}
    case 'SuccessPage':      {return SuccessPage;}
    case 'FailPage':         {return FailPage;}
    }

It works though, but it's a short time solution, like if I had to edit something, it gonna be so hard to change everything (since it's a string)..

like image 811
Yahia Avatar asked Oct 25 '25 10:10

Yahia


1 Answers

2023 - switch with Dart 3.0 Pattern matching

Overview code

class Dog {
  Dog({required this.name});
  final String name;
}

class Cat {
  Cat({required this.name});
  final String name;
}

String checkType(dynamic v) {
  String type;

  switch (v) {
    case Dog(:final name):
      type = 'dog, $name';
    case Cat cat:
      type = 'cat, ${cat.name}';
    case int:
      type = 'int';
    case (String name, String age):
      type = 'Record ($name, $age)';
    case {'user': {'name': final String name, 'age': final int age}}:
      type = 'User Json $name, $age';
    default:
      type = 'unknown';
  }

  return type;
}

Object Destructing

switch (v) {
  case Dog(name:final name):

// or You can skip name if use same name.

switch (v) {
  case Dog(:final name):

⚠️ Docs: They are refuted if the value doesn’t have the same type.

You should use correct type to destructing object.

Just use final or var to indicate data type so you always use same type of object field.

return switch (v) {
  Dog(:String age) => 'dog, $age', // Compile error 'The getter 'age' isn't defined for the type 'Dog'.'
  Dog(name: String otherName) => 'dog, $otherName', // OK, Success to match
  Dog(:int name) => 'dog, $name', // Fail to match
  Dog(:String name) => 'dog, $name', // Success to match, But can't to be reached.

Just assign to variable (can be final with prefix final)

case Cat cat:
  type = 'cat, ${cat.name}';

or

case final Cat cat:
  type = 'cat, ${cat.name}';

Record Destructing

case (String name, String age):
  type = 'Record ($name, $age)';

Map Destructing

case {'user': {'name': final String name, 'age': final int age}}:
  type = 'User Json $name, $age';

You can also use switch expression.

String checkType(dynamic v) {
  return switch (v) {
    Dog(:final name) => 'dog, $name',
    Cat cat => 'cat, ${cat.name}',
    int => 'int',
    (String name, String age) => 'Record ($name, $age)',
    {'user': {'name': final String name, 'age': final int age}} =>
      'User Json $name, $age',
    _ => 'unknown',
  };
}

You can check more information in the Dart docs

like image 152
MJ Studio Avatar answered Oct 26 '25 23:10

MJ Studio