Skip to content
Kezdőlap » Függvények átadása paraméterben

Függvények átadása paraméterben

A függvények átadása paraméterben egy gyakori eset a programozásban. És nem is ördögtől való dolog, mivel a függvényeket változóba tudjuk tenni. Tehát ebben az esetben a változót adjuk át paraméterben, amiben pedig egy függvény lakozik.

Van egy függvényünk, aminek az a feladata, hogy egy state változó értékét állítsa be:

  void switchScreen() {
    setState(
      () {
        activeScreen = const QuestionsScreen();
      },
    );
  }

Ezt a függvényt kellene átadni egy másik widgetnek:

class _QuizState extends State<Quiz> {
  Widget activeScreen = StartScreen();

  void switchScreen() {
    setState(

A kódból látszik, hogy mindez egy StatefulWidgeten belüli state class-ban van. Az activeScreen maga a state változó, ami egy widgetet tartalmaz. Ennek kezdőértéke a StartScreen() widget.

Ebben a StartScreen widgetben van egy gomb, amit megnyomva kell valamit csinálni ezzel a state-el:

OutlinedButton.icon(
  onPressed: () {
  
  },

Tehát az onPressed-en belül kellene valamilyen függvényhívást megvalósítanunk. És jelen példában ez az a függvény, ami kívülről (paraméterként) fog érkezni.

Adjuk át a függvényt paraméterben

Hát adjuk, még pedig így:

Widget activeScreen = StartScreen(switchScreen);

A VSCode jelez egy hibát:

Too many positional arguments hiba

Konkrétan az neki a baja, hogy a StartScreen widget-ben nem mondtuk meg, hogy várjuk ezt a függvényt a paraméterlistában.

A StartScreen widget konstruktorában tehát meg kell adni ezt a függvény paramétert:

class StartScreen extends StatelessWidget {
  const StartScreen(Function startQuiz, {super.key});

Ha precízek akarunk lenni, és miért ne akarnánk, akkor visszagörgetve azt látjuk, hogy maga az átadandó függvény (switchScreen) egy típus nélküli (void) függvény volt. Így ezt illik jelölni a konstruktornál is a függvény paraméter típusánál:

const StartScreen(void Function() startQuiz, {super.key});

Ezt helyesen úgy kell ilyenkor megadni, hogy a Function szó elé beírjuk a void kulcsszót, a Function után pedig () zárójelpárt írunk, mint amikor meghívunk egy függvényt.

Van egy ennél még haladóbb módszer is:

  const StartScreen(this.startQuiz, {super.key});

  final void Function() startQuiz;

Amennyiben mindenképpen számítunk a függvényre, tehát kötelezően várjuk annak átadását, akkor még a required kulcsszót is ki kell tennünk a konstruktorban:

const StartScreen(required this.startQuiz, {super.key});

Átadott függvény használata

A függvényt aztán kétféleképpen tudjuk használni egy gomb onPress tulajdonságában:

onPressed: () {
  startQuiz();
},

Vagy rövidebben:

onPressed: startQuiz,

Átadott függvény hibájának javítása

Ha megnézzük, akkor a VSCode egy újabb hibát jelez ott, ahol a függvényt átadtuk a widgetnek paraméterként:

instance member hiba függvény átadásnál

A hiba azzal van összefüggésben, hogy a függvény paramétert akkor adjuk át, amikor éppen létrehozzuk (és kezdőértékkel ellátjuk) a változót:

class _QuizState extends State<Quiz> {
  Widget activeScreen = StartScreen(switchScreen);

  void switchScreen() {
    setState(
      () {
        activeScreen = const QuestionsScreen();
      },
    );
  }

Tehát a változónak és a függvénynek a létrehozása is ugyanakkor megy végbe időben. Konkrétan akkor, amikor az osztályt példányosítjuk. Tehát az activeScreen és switchScreen létrehozása kb. egymással párhuzamosan történik. Így a Dart úgy gondolja, hogy túl korai hivatkozni a változó inicializálásánál a függvényre, mert alapvetően nem garantált, hogy a függvény / metódus ekkor már létezik. És ez tök jogos is.

Megoldás az initState beépített metódusa:

  Widget activeScreen = StartScreen(switchScreen);

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  void switchScreen() {

Az initState egy olyan metódus, amit a State osztály nyújt nekünk aranytálcán. Az initState-et felül tudjuk írni (@override) a saját inicializációs logikánkkal.

Tehát a nevében is benne van, hogy arra használjuk, amikor extra inicializációs lépéseket akarunk írni akkor, amikor a State objektum először létrejön.

Az initState egyszer fog lefutni, miután az objektum megszületett. Ezután már sosem fog mégegyszer lefutni. Logikus, hogy ezen a metóduson belül kellene elhelyeznünk az activeScreen inicializálását:

  Widget? activeScreen;

  @override
  void initState() {
    activeScreen = StartScreen(switchScreen);
    super.initState();
  }

Az activeScreen létrehozásakor a Widget típusmegnevezés utáni kérdőjellel mondtuk meg azt a Dart-nak, hogy igen, tudomásul vettük, hogy null érték is lehet. Ellenkező esetben a VSCode ismét jelez, ha nem használunk kérdőjelet:

non-nullable hiba

Szóval a ? azt mondja a Dart-nak, hogy a változó tartalmazhat Widgetet vagy null értéket is.

Vélemény, hozzászólás?

Az e-mail címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük