diff --git a/Course.md b/Course.md index bfc101b9bc1de11b5f260cebd48af4e031325a3e..702ab92aea31de40e57ff6af70d7c71015428f05 100644 --- a/Course.md +++ b/Course.md @@ -603,10 +603,10 @@ Strings tip : lower-case -> primitive type, upper-case first -> class -There are of course many more useful built-in types but the main important thing +There are of course many more useful built-in types but the most important thing to -Please note the attention taken to the typographic conventions : while primitive +Please note the attention given to the typographic conventions : while primitive types were written all lowercase, classes (we're not quite ready to define them but we'll get [there](#objects) soon) in Java start with an uppercase letter. Since spaces are not allowed within names, when a name is made of several words, diff --git a/IST-4-JAV.md b/IST-4-JAV.md index 737f8a943b5cf1d95c8ef6aa0955971ca9c09345..ba89733b0963500d69a8806f89889270213497ac 100644 --- a/IST-4-JAV.md +++ b/IST-4-JAV.md @@ -7,5 +7,6 @@ title: IST-4-JAV: Java programming - 2021-09-21 (tue./ç«): the [slides](no-backup/Class1.pdf) - 2021-09-24 (fri./金): the [slides](no-backup/Class2.pdf), the [worksheet](no-backup/Worksheet2.pdf) for practice - 2021-09-28 (tue./ç«): the [slides](no-backup/Class3.pdf), the [worksheet](no-backup/Worksheet3.pdf) for practice -- 2021-10-19 (tue./ç«): the slides -- 2021-10-20 (wed./æ°´): the slides +- 2021-10-19 (tue./ç«): the [slides](no-backup/Class4.pdf), the [worksheet](no-backup/Worksheet4.pdf) for practice +- 2021-10-20 (wed./æ°´): the [slides](no-backup/Class5.pdf), no worksheet but the + [sources](no-backup/EmptyWindow.zip) for the longish empty window : ) diff --git a/Makefile b/Makefile index 1ba44acdcb2435c1a07de62463e80b736fb7f675..b97c3e80c6bc0d41bea4141906dafece03f957dc 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ pdfs = $(foreach f,$(wildcard $(1)/*.md),$(patsubst %.md,%.pdf,$(f))) MODEL_PARALLELOGRAM = $(call graphs,$(foreach i,0 1 2 3,parallelogram$(i))) INHERITANCE_GRAPHS = $(call graphs,classesTree exceptionsTree) IMPLEMENTATION_GRAPHS = $(call graphs,arrayList implementations linkedList newCellArrayList newCellLinkedList) +BOX = $(call graphs,nestedBox) SLIDES = $(call pdfs,Slides) WORKSHEET = $(call pdfs,Worksheet) @@ -18,6 +19,7 @@ Course.pdf: Course.md $(MODEL_PARALLELOGRAM) Slides/Class1.pdf: $(MODEL_PARALLELOGRAM) figures/helloworld.tex Slides/Class3.pdf: $(INHERITANCE_GRAPHS) Slides/Class4.pdf: $(IMPLEMENTATION_GRAPHS) +Slides/Class4.pdf: $(BOX) Slides/%.pdf: Slides/%.md pandoc --toc --slide-level=3 -t beamer $< -o $@ diff --git a/Slides/Class4.md b/Slides/Class4.md index 289d8f1d37c3a4ede4453870481393ba3814c7e7..fe0c63bf46bd932c2712d4d6ad8f478663d922f6 100644 --- a/Slides/Class4.md +++ b/Slides/Class4.md @@ -350,7 +350,7 @@ $\Rightarrow$ function literals assuming -- `(a, b, …)` is a tuple of $n$ expressions (parentheses optional when 1 only) +- `(a, b, …)` is a tuple of $n$ variables (parentheses optional when 1 only) - `e` is an expression - `b` is a block ending with a `return` statement @@ -556,7 +556,7 @@ $\Rightarrow$ No "one-size-fits-all", implementation should match the use - "white pages", phone books… - Domain Name System - looking up users in a table by their ID -- retrieving +- finding the selected action in a menu ```Java interface Map<K, V> { @@ -634,10 +634,3 @@ V get(Object k) { - fast access - fast insertion - resizing costs when it gets too full (initial capacity / load factor) - -:::columns -::::column -:::: -::::column -:::: -::: diff --git a/Slides/Class5.md b/Slides/Class5.md index 15c384b795068a37c44b0281ca0728eb8e9c436b..91ed4563f20f37ea196e1642f93bd35e2a89c2ec 100644 --- a/Slides/Class5.md +++ b/Slides/Class5.md @@ -1,6 +1,453 @@ --- title: IST-4-JAV Java Programming -subtitle: Slides - Class 5 -date: 2021-10-19 +subtitle: Class 5 - The devil in the details +author: Alice BRENON `<alice.brenon@liris.cnrs.fr>` +date: 2021-10-20 +header-includes: + \usepackage{fdsymbol} + \usepackage{textgreek} + \usepackage{bclogo} + \usepackage{hyperref} + \usepackage{color} + \definecolor{yellow}{RGB}{255, 127, 0} + \definecolor{greyblue}{RGB}{58, 103, 183} + \hypersetup{ + colorlinks, + linkcolor = yellow, + urlcolor = greyblue + } + \usetheme{Frankfurt} + \usecolortheme{seahorse} --- +# Architecture + +## Patterns + +### Origins + +#### Approach + +- how to handle large projects ? +- experience as a programmer (c.f. chess) +- similarities from one project to the other + +$\rightarrow$ programming as a *craft* vs. programming as *science* + +#### A famous book + + +:::columns +::::column + +- "Design Patterns: Elements of Reusable Object-Oriented Software" +- four authors ("gang of four"), (1994) +- huge best-seller, impact on the community +- presents 23 patterns + +:::: +::::column + +\vspace{0.3cm} + +{height=100px} + +:::: +::: + +### Controverse + +Very praised in 1994 +…then progressively criticized + +- useless or redundant patterns +- attacks against the concept of "pattern" itself + + symptoms of "faults" in the language + + missing features + +\vspace{1cm} + +$\rightarrow$ Part of Java's history + +### Singleton: about + +- ensure one instance only +- typical use: logger +- like a global variable + lazy loading + +### Singleton: example + +```Java +class Logger { + private static Logger instance; + private Logger() { + System.out.println("Created a logger"); + } + public static Logger getInstance() { + if(Logger.instance == null) { + instance = new Logger(); + } + return Logger.instance; + } +} + +``` + +### Factory: about + +- hide the constructor ("alternative constructors") +- level some internal complexity +- decouple the consumer class and the choice of a particular implementation + +### Factory: example + +```Java +class Sound { + private MP3 mp3Data; + private Ogg oggData; + private Sound(MP3 mp3Data) { + this.mp3Data = mp3Data; + } + private Sound(Ogg oggData) { + this.oggData = oggData; + } + public fromFile(String path) { + if(… == ".mp3") { + return new Sound(new MP3(path)); + } else { + return new Sound(new Ogg(path)); + } + } +``` + +### Decorator: about + +- add behaviour to a particular instance, not the whole class +- dynamic modification of functionality +- idea of "wrapping" around an existing object +- $\neq$ inheritance (runtime vs. compile-time) +- (inheritance *à la* Javascript) +- **circling around the same interface** + +### Decorator: example 1/2 + +```Java +interface Cat { + public String getDescription(); +} + +class AnyCat implements Cat { + public String getDescription() { + return "A cat"; + } +} +``` + +### Decorator: example 2/2 + +```Java +abstract class CatDecorator implements Cat { + private final Cat decoratedCat; + public CatDecorator(Cat c) { + this.decoratedCat = c; + } + public String getDescription() { + return this.decoratedCat.getDescription(); + } +} + +class WithHat extends CatDecorator { + public WithHat(Cat c) { super(c); } + public String getDescription() { + return super.getDescription() + " with a hat"; + } +} +``` + +### MVC: about + +- Model — View — Controller +- even earlier than the "Design patterns" book ! (1978) +- general principle of "Separation of concerns", modularity, etc. + +### Model: example + +```Java +class VolumeState { + private float volume = 0.5f; + private boolean mute = false; + public void changeVolume(float deltaVolume) { + float newVolume = this.volume + deltaVolume; + this.volume = Math.min(1, Math.max(0, newVolume)); + } + public void toggleMute() { + this.mute = !this.mute; + } + public float getVolume() { + return this.mute ? 0 : this.volume; + } +} +``` + +### Controller + +```Java +class Knob { + private VolumeState volumeState; + public Knob (VolumeState volumeState) { + this.volumeState = volumeState; + } + public void handle(String command) { + switch(command) { + case "+": + this.volumeState.changeVolume(0.05f); break; + case "-": + this.volumeState.changeVolume(-0.05f); break; + case "m": this.volumeState.toggleMute(); break; + default: System.err.println("Unknown: " + command); + } + } +} +``` + +### View: example + +```Java +class VolumeBar { + private byte width; + private VolumeState volumeState; + private Knob knob; + public VolumeBar(byte width, VolumeState volumeState) { + this.width = width; + this.volumeState = volumeState; + this.knob = new Knob(volumeState); + } + … +``` + +### View: continued + +```Java + … + public void run() { + while(true) { + display(this.volumeState.getVolume()); + this.knob.handle(System.console().readLine()); + } + } + public void display(float level) { + char[] bar = new char[(int) (level * this.width)]; + for(int i = 0; i < bar.length; i++) { + bar[i] = '#'; + } + System.out.println(bar); + } +} +``` + +## Inline classes + +### Implementing interfaces + +- can be done on the fly ! +- "anonymous classes", like lambdas but heavier + +```Java +package javax.swing; +class SwingUtilities { + … + public static void invokeLater(Runnable doRun); +} +``` + +commonly found in Swing examples: + +```Java +javax.swing.SwingUtilities.invokeLater(new Runnable() { + public void run() { + createAndShowGUI(); + } +}); +``` + +### Ad-hoc inheritance + +- `abstract` as "negative" methods +- $\rightarrow$ "settle the bill" +- even `abstract` classes can be instantiated ! + +```Java +enum Color { + RED, GREEN, YELLOW, BLACK, BLUE +} +abstract class Beverage { + abstract public Color getColor(); +} +Beverage someUnknownStuff = new Beverage() { + public Color getColor() { return Color.GREEN; } +} +``` + +# Graphical User Interfaces + +## Libraries + +### AWT + +**Basic tooling** + +- older +- events (key presses) +- notion of `Component` +- `Graphics` surface to draw +- definition of `Layout` + +```Java +import java.awt.*; +import java.awt.event.*; +… +``` + +### Swing + +**More advanced** + +- more recent +- heavily depends on AWT anyway +- advanced widgets: dialogs, etc +- easier styling + +```Java +import javax.swing.*; +import javax.swing.colorchooser.*; +import javax.swing.plaf.*; // pluggable look-and-feel +``` + +### General idea + +**a tree of components** + +- you plug components into containers (also components) +- recursively up to the root window +- components can appear only once + +{height=80px} + +### The 2D API + +- within `AWT` +- useful for: + + geometric primitives + + text + + images + +#### Another approach + +- you implement `Component` +- a `Graphics` object is passed around in the `paint` method +- you draw to it + +### Documentation + +#### Packages + +[https://docs.oracle.com/javase/7/docs/api/overview-summary.html](https://docs.oracle.com/javase/7/docs/api/overview-summary.html) + +#### Tutorials to AWT's 2D API + +[https://docs.oracle.com/javase/tutorial/2d/overview/index.html](https://docs.oracle.com/javase/tutorial/2d/overview/index.html) + +#### Tutorials to Swing components + +[https://docs.oracle.com/javase/tutorial/uiswing/components/index.html](https://docs.oracle.com/javase/tutorial/uiswing/components/index.html) + +#### Swing examples + +[https://docs.oracle.com/javase/tutorial/uiswing/examples/components/index.html](https://docs.oracle.com/javase/tutorial/uiswing/examples/components/index.html) + +## Simple example + +### Minimal window + +```Java +import javax.swing.*; +public class EmptyWindow { + private static void createAndShowGUI() { + JFrame frame = new JFrame("Some window title"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.pack(); + frame.setVisible(true); + } + public static void main(String[] args) { + SwingUtilities.invokeLater(() -> createAndShowGUI()); + } +} +``` + +### With a panel + +```Java +import java.awt.GridLayout; + … + private static void createAndShowGUI() { + … + JPanel jpanel = new JPanel(new GridLayout(2, 2)); + frame.getContentPane().add(jpanel); + … + } + +``` + +### With a couple widgets + +```Java + … + private static void createAndShowGUI() { + … + JLabel label = new JLabel("Hey there !"); + JTextField input = new JTextField(); + JButton submit = new JButton("click me"); + jpanel.add(label); + jpanel.add(input); + jpanel.add(submit); + … + } +``` + +### Add reactions to events + +```Java +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; + … + private static void createAndShowGUI() { + … + submit.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + System.out.println("Received " + e); + } + }); + … + } +``` + +### Display image + +```Java +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.*; +import javax.imageio.ImageIO; + +class ImageViewer extends Component { + private BufferedImage img; + ImageViewer(String path) { + try { + img = ImageIO.read(new File(path)); + } catch (IOException e) {} + } + public void paint(Graphics g) { + g.drawImage(this.img, 0, 0, null); + } +} +```