Skip to main content

Symbol

Symbols in Dart zijn objecten die een operator of identifier vertegenwoordigen die in een Dart-programma is gedeclareerd. Symbolen worden meestal gebruikt in reflectie en bij het werken met identifier-namen. Ze zijn nuttig omdat ze tijdens de runtime veilig kunnen worden gemanipuleerd, zelfs na minificatie van de code.

Basisgebruik van Symbolen

Je kunt een symbool maken met een symbol-literal, die begint met een hashtag (#) gevolgd door de identifier:

void main() {
  Symbol sym = #myIdentifier;
  print(sym);  // Output: Symbol("myIdentifier")
}

In dit voorbeeld wordt een symbool gemaakt voor de identifier myIdentifier.

Symbolen en Reflectie

Reflectie in Dart maakt het mogelijk om te interageren met objecten en hun members tijdens runtime, zelfs als je de namen van deze members niet kent tijdens het schrijven van de code. Symbolen zijn hierbij essentieel omdat ze ervoor zorgen dat je kunt werken met identifiers zonder te hoeven vertrouwen op hun stringrepresentaties, wat belangrijk is voor het behoud van code na minificatie.

Reflectie in Dart wordt mogelijk gemaakt door de dart:mirrors library. Hier is een uitgebreid voorbeeld:

import 'dart:mirrors';

class MyClass {
  void myMethod() {
    print('Hello from myMethod!');
  }

  void anotherMethod() {
    print('Hello from anotherMethod!');
  }
}

void main() {
  MyClass myClass = MyClass();
  Symbol methodName = #myMethod;
  
  // Reflectie om myMethod aan te roepen
  InstanceMirror instanceMirror = reflect(myClass);
  instanceMirror.invoke(methodName, []);

  // Reflectie om alle methoden aan te roepen
  ClassMirror classMirror = instanceMirror.type;
  for (var declaration in classMirror.declarations.values) {
    if (declaration is MethodMirror && !declaration.isConstructor) {
      instanceMirror.invoke(declaration.simpleName, []);
    }
  }
}

In dit voorbeeld gebruiken we reflectie om myMethod en anotherMethod van een instantie van MyClass aan te roepen. We gebruiken symbolen om de namen van de methoden te representeren.

Vergelijking van Symbolen

Symbolen kunnen worden vergeleken met behulp van de == operator. Dit is handig wanneer je symbolen wilt vergelijken zonder de stringrepresentaties te gebruiken.

Voorbeeld:

void main() {
  Symbol sym1 = #myIdentifier;
  Symbol sym2 = #myIdentifier;
  Symbol sym3 = #anotherIdentifier;

  print(sym1 == sym2);  // Output: true
  print(sym1 == sym3);  // Output: false
}

In dit voorbeeld vergelijken we verschillende symbolen om te controleren of ze gelijk zijn.

Symbolen en Minificatie

Een van de belangrijkste voordelen van symbolen is dat ze de consistentie van identifiers behouden, zelfs na minificatie van de code. Minificatie is het proces van het verkleinen van de grootte van de code door de namen van variabelen, functies en andere identifiers te verkorten. Symbolen zorgen ervoor dat de referenties naar deze identifiers correct blijven, zelfs als de namen worden gewijzigd.

Voorbeeld zonder minificatie:

void main() {
  Symbol sym = #myIdentifier;
  print(sym);  // Output: Symbol("myIdentifier")
}

Voorbeeld met minificatie (hypothetisch):

void main() {
  Symbol sym = #a;
  print(sym);  // Output: Symbol("a")
}

Zelfs als de identifier myIdentifier wordt verkort naar a tijdens minificatie, blijft de symbolische referentie correct.

Symbolen en Dynamische Toegang

In sommige gevallen kan het nodig zijn om dynamisch toegang te krijgen tot members van een object. Symbolen kunnen hierbij helpen door te zorgen voor veilige toegang, zelfs als de exacte namen van de members niet bekend zijn tijdens het schrijven van de code.

Voorbeeld:

import 'dart:mirrors';

class DynamicAccess {
  void sayHello() {
    print('Hello!');
  }
}

void main() {
  DynamicAccess dynamicAccess = DynamicAccess();
  Symbol methodName = #sayHello;

  InstanceMirror instanceMirror = reflect(dynamicAccess);
  instanceMirror.invoke(methodName, []);
}

In dit voorbeeld gebruiken we een symbool om dynamisch toegang te krijgen tot de sayHello methode van de DynamicAccess klasse.

Symbols in Dart zijn krachtige hulpmiddelen voor het werken met identifiers en reflectie. Ze bieden een veilige manier om met identifier-namen om te gaan, zelfs na minificatie van de code, en zijn essentieel voor dynamische toegang en reflectie. Door symbols te gebruiken, kun je flexibeler en robuuster code schrijven die minder gevoelig is voor veranderingen in de identifier-namen.