Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Resultatet er uansett at navnene i den importerte modulen er tilgjengelig, altså at notatarket tilsvarende modulen er opprettet. Det kan bare være ett slikt ark pr. modul, og det er derfor import-setningen bare kjører modulen hvis den ikke allerede er blitt utført. Når en siden ønsker å referere til funksjoner inni modulen, så bruker en metodenavnet modulnavnet og punktum som prefix foran funksjonsnavnet, f.eks.

...

Java sine moduler kalles klasser, og er lik moduler på den måten at de deklarerer variabler og funksjoner (kalles metoder i Java), og kjører metodene i kontekst av et notatark med variablene i. En viktig forskjell er imidlertid at en kan ha mange slik notatark med de samme variablene i (men selvsagt forskjellige verdier) og at alle disse må opprettes manuelt. Som regel vil en lagre referanser til disse, slik at en kan referere til dem siden, og f.eks. kalle metodene, omtrent på samme måte som en i Python kaller funksjoner i moduler.

Når rpncalc5ui-modulen i Python-koden over bruker rpncalc4core-navnet direkte, så må en i Java istedet lage en instans av RPNCalc4Core-klassen og lagre denne i en variabel, for så å referere vha. denne:

Code Block
languagejava
RPNCalcCoreRPNCalc4Core rpnCalcCorerpnCalc4Core = new RPNCalcCoreRPNCalc4Core();
...
if (rpnCalcCorerpnCalc4Core.isOperand(token)) {
	...
}

Merk at det er ingen regel som sier at en må gi en variabel et navn som ligner på klassen, men det gjør koden lettere å lese.

En kan tegne dette som et objekt-diagram, som illustrerer hvordan RPNCalc4UI- og RPNCalc4Core-objektene henger sammen:

PlantUML Macro
object RPNCalc4UI {
}

object RPNCalc4Core {
	operands = ...
}

RPNCalc4UI -> RPNCalc4Core

Her er hele koden:

Code Block
languagejava
package python;

import java.util.ArrayList;
import java.util.List;

public class RPNCalc4Core {

    // deklarerer lista og setter den til en tom lista
    List<Double> operands = new ArrayList<Double>();

    boolean isOperand(String token) {
        // bruker samme teknikk som i Python:
        // kall konverteringsmetoden for String til desimaltall og returner true hvis det går
        try {
            Double.valueOf(token);
            return true;
        } catch (NumberFormatException nfe) {
            return false;
        }
    }

    List<Double> popOperands(int n) {
        if (operands.size() < n) {
            return null;
        }
        // må lage en ny liste, som fylles med de bakerste elementene i operands-lista
        List<Double> result = new ArrayList<Double>(n);
        while (n > 0) {
            // remove med angitt indeks fjerner og returnerer siste element
            double lastElement = operands.remove(operands.size() - 1);
            // elementet må legges først i lista, for å unngå å snu rekkefølgen
            result.add(0, lastElement);
            n = n - 1;
        }
        return result;
    }

    void plus() {
        // pop to operander, hvis mulig
        List<Double> ops = popOperands(2);
        // hvis det fantes to operander, så summeres de og push-es tilbake
        if (ops != null) {
            pushOperands(ops.get(0) + ops.get(1));
        }
    }

    void minus() {
        // pop to operander, hvis mulig
        List<Double> ops = popOperands(2);
        // hvis det fantes to operander, så beregnes differansen de og push-es tilbake
        if (ops != null) {
            pushOperands(ops.get(0) - ops.get(1));
        }
    }
    
    void printOperands() {
        System.out.println(operands);
    }

    void pushOperands(double operand) {
        // legg til bakerst
        operands.add(operand);
    }
}
Code Block
languagejava
package python;

import java.util.Scanner;

public class RPNCalc4UI {

    RPNCalc4Core rpnCalc4Core = new RPNCalc4Core();

    void run() {
        // en Scanner hjelper oss å lese inn og tolke tekst
        // System.in dvs. konsollet, brukes som datakilde for Scanner-objektet
        Scanner scanner = new Scanner(System.in);
        while (true) {
            rpnCalc4Core.printOperands();
            System.out.print(" > ");
            String token = scanner.next();
            if (rpnCalc4Core.isOperand(token)) {
                double operand = Float.valueOf(token);
                rpnCalc4Core.pushOperands(operand);
            } else if (token.equals("exit")) {
                break;
            } else if (token.equals("+")) {
                rpnCalc4Core.plus();
            } else if (token.equals("-")) {
                rpnCalc4Core.minus();
            } else {
                System.out.println("Unsupported operator: " + token);
            }
        }
        // en Scanner må lukkes når vi er ferdig med den
        scanner.close();
        System.out.println("program exited");
    }

    // den obligatoriske oppstartsmetoden for programklasser
    public static void main(String[] args) {
        // vi lager en instans av program-klassen og lar den ta over
        new RPNCalc4UI().run();
    }
}