abstract class Pastry {
abstract public void printMe ();
abstract public int getCalories ();
}
class Beignet extends Pastry {
@Override
public void printMe() {
System.out.println ("It's a beignet");
}
public int getCalories() {
return 300;
}
}
class Cruller extends Pastry {
@Override
public void printMe() {
System.out.println ("It's a cruller");
}
public int getCalories() {
return 400;
}
}
class PastryTest1 {
public static void main (String[] args) {
var ps = new Pastry[] {new Beignet(), new Cruller()};
int calories = 0;
for (var p : ps) {
p.printMe();
calories += p.getCalories();
}
System.out.println(calories);
}
}
$ javac PastryTest1.java && java PastryTest1 It's a beignet It's a cruller 700
enum Pastry:
case Beignet
case Cruller
import Pastry.*
def printPastry (p: Pastry) =
p match
case Beignet => println("It's a Beignet")
case Cruller => println("It's a Cruller")
def getCalories (p: Pastry) =
p match
case Beignet => 300
case Cruller => 400
def main(args:Array[String]) =
var ps = List(Beignet, Cruller)
for (p <- ps) do printPastry(p)
println (ps.foldLeft(0)((z,p) => z+getCalories(p)))
$ scala Pastry.scala It's a Beignet It's a Cruller 700
interface PastryVisitor {
public void visitBeignet(Beignet beignet);
public void visitCruller(Cruller cruller);
}
abstract class Pastry {
public abstract void accept(PastryVisitor visitor);
}
class Beignet extends Pastry {
@Override
public void accept(PastryVisitor visitor) {
visitor.visitBeignet(this);
}
}
class Cruller extends Pastry {
@Override
public void accept(PastryVisitor visitor) {
visitor.visitCruller(this);
}
}
class PastryPrinter implements PastryVisitor {
public void visitBeignet(Beignet beignet) {
System.out.println ("It's a beignet");
}
public void visitCruller(Cruller cruller) {
System.out.println ("It's a cruller");
}
}
public class PastryTest3 {
public static void main (String[] args) {
var printer = new PastryPrinter ();
var ps = new Pastry[] {new Beignet(), new Cruller()};
for (var p : ps) {
p.accept(printer);
}
}
}
$ javac PastryTest3.java && java PastryTest3 It's a beignet It's a cruller
interface PastryVisitor<T> {
public T visitBeignet(Beignet beignet);
public T visitCruller(Cruller cruller);
}
abstract class Pastry {
public abstract <T> T accept(PastryVisitor<T> visitor);
}
class Beignet extends Pastry {
@Override
public <T> T accept(PastryVisitor<T> visitor) {
return visitor.visitBeignet(this);
}
}
class Cruller extends Pastry {
@Override
public <T> T accept(PastryVisitor<T> visitor) {
return visitor.visitCruller(this);
}
}
class PastryPrinter implements PastryVisitor<Void> {
public Void visitBeignet(Beignet beignet) {
System.out.println ("It's a beignet");
return null;
}
public Void visitCruller(Cruller cruller) {
System.out.println ("It's a cruller");
return null;
}
}
class GetCalories implements PastryVisitor<Integer> {
public Integer visitBeignet(Beignet beignet) {
return 300;
}
public Integer visitCruller(Cruller cruller) {
return 400;
}
}
public class PastryTest2 {
public static void main (String[] args) {
var printer = new PastryPrinter ();
var getCals = new getCalories ();
var ps = new Pastry[] {new Beignet(), new Cruller()};
int calories = 0;
for (var p : ps) {
p.accept(printer);
calories += p.accept(getCals);
}
System.out.println(calories);
}
}
$ javac PastryTest2.java && java PastryTest2 It's a beignet It's a cruller 700
Simple language with two binary operators
expr → expr "-" expr [Subtraction] expr → expr "÷" expr [Division] expr → NUMBER
abstract class Expr {
public abstract String print ();
public abstract int eval ();
}
class SubExpr extends Expr {
public Expr left;
public Expr right;
public SubExpr (Expr left, Expr right) {
this.left = left;
this.right = right;
}
@Override
public String print () {
String left = this.left.print ();
String right = this.right.print ();
return "( " + left + " - " + right + " )";
}
@Override
public int eval () {
int left = this.left.eval ();
int right = this.right.eval ();
return left - right;
}
}
class DivExpr extends Expr {
public Expr left;
public Expr right;
public DivExpr (Expr left, Expr right) {
this.left = left;
this.right = right;
}
@Override
public String print () {
String left = this.left.print ();
String right = this.right.print ();
return "( " + left + " / " + right + " )";
}
@Override
public int eval () {
int left = this.left.eval ();
int right = this.right.eval ();
return left / right;
}
}
class NumExpr extends Expr {
public int num;
public NumExpr (int num) {
this.num = num;
}
@Override
public String print () {
return Integer.toString(this.num);
}
@Override
public int eval () {
return this.num;
}
}
public class ExprTest1 {
public static void main (String[] args) {
var expr = new SubExpr (new NumExpr (9), new DivExpr (new NumExpr(6), new NumExpr (3)));
System.out.println (expr.print());
System.out.println (expr.eval());
}
}
$ javac ExprTest1.java && java ExprTest1 ( 9 - ( 6 / 3 ) ) 7
enum Expr:
case SubExpr (left: Expr, right: Expr)
case DivExpr (left: Expr, right: Expr)
case NumExpr (num: Int)
import Expr.*
def printExpr (e: Expr) : String =
e match
case SubExpr (left, right) => "( " + printExpr(left) + " - " + printExpr(right) + " )"
case DivExpr (left, right) => "( " + printExpr(left) + " / " + printExpr(right) + " )"
case NumExpr (num) => num.toString
def evalExpr (e: Expr) : Int =
e match
case SubExpr (left, right) => evalExpr(left) - evalExpr(right)
case DivExpr (left, right) => evalExpr(left) / evalExpr(right)
case NumExpr (num) => num
def main(args:Array[String]) =
val expr = SubExpr (NumExpr (9), DivExpr (NumExpr(6), NumExpr (3)));
println (printExpr (expr))
println (evalExpr (expr))
$ scala Expr.scala ( 9 - ( 6 / 3 ) ) 7
interface ExprVisitor<T> {
public T visitSubExpr(SubExpr expr);
public T visitDivExpr(DivExpr expr);
public T visitNumExpr(NumExpr expr);
}
abstract class Expr {
public abstract <T> T accept(ExprVisitor<T> visitor);
}
class SubExpr extends Expr {
public Expr left;
public Expr right;
public SubExpr (Expr left, Expr right) {
this.left = left;
this.right = right;
}
@Override
public <T> T accept(ExprVisitor<T> visitor) {
return visitor.visitSubExpr(this);
}
}
class DivExpr extends Expr {
public Expr left;
public Expr right;
public DivExpr (Expr left, Expr right) {
this.left = left;
this.right = right;
}
@Override
public <T> T accept(ExprVisitor<T> visitor) {
return visitor.visitDivExpr(this);
}
}
class NumExpr extends Expr {
public int num;
public NumExpr (int num) {
this.num = num;
}
public <T> T accept(ExprVisitor<T> visitor) {
return visitor.visitNumExpr(this);
}
}
class ExprPrinter implements ExprVisitor<String> {
public String visitSubExpr(SubExpr expr) {
String left = expr.left.accept(this);
String right = expr.right.accept(this);
return "( " + left + " - " + right + " )";
}
public String visitDivExpr(DivExpr expr) {
String left = expr.left.accept(this);
String right = expr.right.accept(this);
return "( " + left + " / " + right + " )";
}
public String visitNumExpr(NumExpr expr) {
return Integer.toString(expr.num);
}
}
class ExprEvaluator implements ExprVisitor<Integer> {
public Integer visitSubExpr(SubExpr expr) {
Integer left = expr.left.accept(this);
Integer right = expr.right.accept(this);
return left - right;
}
public Integer visitDivExpr(DivExpr expr) {
Integer left = expr.left.accept(this);
Integer right = expr.right.accept(this);
return left / right;
}
public Integer visitNumExpr(NumExpr expr) {
return expr.num;
}
}
public class ExprTest2 {
public static void main (String[] args) {
var printer = new ExprPrinter ();
var evaluator = new ExprEvaluator ();
var expr = new SubExpr (new NumExpr (9), new DivExpr (new NumExpr(6), new NumExpr (3)));
System.out.println (expr.accept(printer));
System.out.println (expr.accept(evaluator));
}
}
$ javac ExprTest2.java && java ExprTest2 ( 9 - ( 6 / 3 ) ) 7
expression → literal | unary | binary | grouping literal → NUMBER | STRING | "true" | "false" | "nil" grouping → "(" expression ")" unary → ( "-" | "!" ) expression binary → expression operator expression operator → "==" | "!=" | "<" | "<=" | ">" | ">=" | "+" | "-" | "*" | "/"