diff --git a/_config.yml b/_config.yml index 863e7af1a5a8826630575ee8243fa410a6aef07b..0801788b10f4c947aaf4a0d89f5dcdf5fe5b7662 100644 --- a/_config.yml +++ b/_config.yml @@ -7,26 +7,28 @@ title: Interaction Programming (CSE 340) description: Interactive Tech is changing society. Help invent the future! -baseurl: "/courses/csexxx/xxqq" +baseurl: "/courses/cse340/21wi" url: https://courses.cs.washington.edu # the base hostname & protocol for your site, e.g. http://example.com -twitter_username: username -git_username: username -git_url: https://gitlab.cs.washington.edu/jmankoff/class-website-core -git_branch: CSExxx-xxQQ -piazza: https://us.edstem.org/courses/xxx/discussion/ -canvas: https://canvas.uw.edu/courses/xxxxx -gitlab: https://gitlab.cs.washington.edu/students-group-for-assignments -gitgrade: https://gitgrade.cs.washington.edu/student/summary/xxxx +twitter_username: jcmankoff +git_username: jmankoff +git_url: https://gitlab.cs.washington.edu/cse340-21wi-tas +git_branch: CSE340-WI21 +piazza: https://us.edstem.org/courses/381/discussion/ +canvas: https://canvas.uw.edu/courses/1370612 +gitlab: https://gitlab.cs.washington.edu/cse340-21wi-students +gitgrade: https://gitgrade.cs.washington.edu/student/summary/8723 +hcibook: "No HCI Textbook, just readings" +androidbook: "No Android Textbook, just readings" paginate: 5 -quarter: "Quarter YYYY" +quarter: "Winter 2021" copydate: "3/30/20" status: draft author: - name: Name - url: "https://website" + name: Jennifer Mankoff + url: "https://make4all.org/jennifer-mankoff/" -email: "email@university.edu" # Your contact email +email: "jmankoff@uw.edu" # Your contact email # probably want to update this to be the class teaching staff mailing list # The Reveal theme diff --git a/_config_production.yml b/_config_production.yml index 863e7af1a5a8826630575ee8243fa410a6aef07b..0801788b10f4c947aaf4a0d89f5dcdf5fe5b7662 100644 --- a/_config_production.yml +++ b/_config_production.yml @@ -7,26 +7,28 @@ title: Interaction Programming (CSE 340) description: Interactive Tech is changing society. Help invent the future! -baseurl: "/courses/csexxx/xxqq" +baseurl: "/courses/cse340/21wi" url: https://courses.cs.washington.edu # the base hostname & protocol for your site, e.g. http://example.com -twitter_username: username -git_username: username -git_url: https://gitlab.cs.washington.edu/jmankoff/class-website-core -git_branch: CSExxx-xxQQ -piazza: https://us.edstem.org/courses/xxx/discussion/ -canvas: https://canvas.uw.edu/courses/xxxxx -gitlab: https://gitlab.cs.washington.edu/students-group-for-assignments -gitgrade: https://gitgrade.cs.washington.edu/student/summary/xxxx +twitter_username: jcmankoff +git_username: jmankoff +git_url: https://gitlab.cs.washington.edu/cse340-21wi-tas +git_branch: CSE340-WI21 +piazza: https://us.edstem.org/courses/381/discussion/ +canvas: https://canvas.uw.edu/courses/1370612 +gitlab: https://gitlab.cs.washington.edu/cse340-21wi-students +gitgrade: https://gitgrade.cs.washington.edu/student/summary/8723 +hcibook: "No HCI Textbook, just readings" +androidbook: "No Android Textbook, just readings" paginate: 5 -quarter: "Quarter YYYY" +quarter: "Winter 2021" copydate: "3/30/20" status: draft author: - name: Name - url: "https://website" + name: Jennifer Mankoff + url: "https://make4all.org/jennifer-mankoff/" -email: "email@university.edu" # Your contact email +email: "jmankoff@uw.edu" # Your contact email # probably want to update this to be the class teaching staff mailing list # The Reveal theme diff --git a/assets/css/style.scss b/assets/css/style.scss index d49312b1457c6c1ffe0260780db223b586bb1ff7..22fcd4f118e4bc83a81be2fb1878eeefb67f85da 100644 --- a/assets/css/style.scss +++ b/assets/css/style.scss @@ -1,10 +1,10 @@ --- # This is where the style colors for the website are set --- -$navbar-color: #003459; -$dark-color: #003459; -$gradient-dark: #004d85; -$gradient-light: #004d85; +$navbar-color: #3a1c6f; +$dark-color: #3a1c6f; +$gradient-dark: #3a1c6f; +$gradient-light: #006666; $lecture-background: #164756 ; $lab-background:#d8e6c9; $background: #d8e6c9; @@ -120,7 +120,7 @@ dl dt.lab { } .navbar { - background-color: $navbar-color; + background-color: $gradient-dark; } table.schedule { diff --git a/docs/index.md b/docs/index.md index bea510f6b665593e7912f743f56071224b11c07f..ba11d1e5e55d9d83c70b03752c623c7e4ac23f8d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -21,4 +21,6 @@ slowly and will continue to be added to. - [Debugging]({{site.baseurl}}/docs/dev_mode) - [Android File Explorer]({{site.baseurl}}/docs/android_files) -- [Java 101]({{site.baseurl}}/docs/java.html) +- [Java 101]({{site.baseurl}}/docs/java/java.html) +- [Advanced Java]({{site.baseurl}}/docs/java/java-advanced.html) +- [Java example code]({{site.baseurl}}/docs/java/JavaRefresher.zip) diff --git a/docs/java/JavaRefresher.zip b/docs/java/JavaRefresher.zip new file mode 100644 index 0000000000000000000000000000000000000000..25f27c4c6f164f4fa2ad7b747dc793d0083ec75d Binary files /dev/null and b/docs/java/JavaRefresher.zip differ diff --git a/docs/java/java-advanced.html b/docs/java/java-advanced.html new file mode 100644 index 0000000000000000000000000000000000000000..2b1e57a58736db7a29c7dcc9bfc41f7f73d0cd24 --- /dev/null +++ b/docs/java/java-advanced.html @@ -0,0 +1,219 @@ +--- +layout: presentation +title: Advanced Java +description: Advanced Java Slides +class: middle, center, inverse +--- +name: inverse +layout: true +class: center, middle, inverse +--- + +# CSE 340 ({{site.quarter}}) +## Advanced Java + +--- +layout: false + +# Roadmap +- Inheritance +- Generics +- Anonymous Inner Classes +- Lambdas (and `::` notation) + +--- +# Inheritance + +.left-column50[ +Interfaces: a promise that you will implement these methods +- Interfaces can only implement other interfaces +- A class can implement many interfaces +- Examples: Comparable interface + +Regular class: fully defined behaviors that you want to add to +- All functions in the parent class have been implemented and are inherited +- Usually would use this to add more specific behavior by changing implementation or adding new methods +] +.right-column50[ +Abstract classes: like interfaces but has some fully implemented methods as well +- Can have abstract functions that are only defined in subclasses like interfaces +- Also allows you to define shared member variables and functions for all subclasses +- Examples: Pets all have a name (inherited member variable), are adopted the +same way (function defined in abstract class) but eat different foods (abstract function defined only in subclasses) + +.small.red[https://courses.cs.washington.edu/courses/cse331/20wi/lectures/lec12-subtyping.pdf] +] + +--- +# Inheritance common errors and tips +Be careful: +- Make sure not to redefine a variable you inherited from a parent class +- Check and make sure that you are using the same method signature (return types and parameter types) when overriding inherited methods, otherwise this is actually overloading +- These might lead to undefined and weird behaviors! :( + +Remember: +- You can only subclass one class, but you can implement as many interfaces as you want +- Subclasses are able to access and change public and protected member variables of parent +- You must implement interface methods and all abstract superclass methods + +--- +# Switch Statements + +A form of a conditional with different execution paths + +```java +public enum EssentialGeometry { INSIDE, ON_EDGE, OUTSIDE }; +... +EssentialGeometry where = EssentialGeometry.INSIDE; +switch (where) { + case ON_EDGE: // do the edgy things + break; // and skip everything after this + case INSIDE: // do the inside things but also fall through + // and do the OUTSIDE things because no break statement; + case OUTSIDE: // do the outside things + break; // and skip everything after this + default: // do default things + // automatically falls through +} +``` +--- +# Private class fields are often labelled with a lowercase “m†at the front + +This notation comes from AOSP<br> +(Android Open Source Project) [Code Style Guidelines for Contributors](http://source.android.com/source/code-style.html#follow-field-naming-conventions) + +Follow Field Naming Conventions +- Non-public, non-static field names start with ‘m’. +- Static field names start with ‘s’. +- Other fields start with a lower case letter. +- Public static final fields (constants) are `ALL_CAPS_WITH_UNDERSCORES`. + +For example: +- `private float mCircleRadius, mThumbRadius;` +- `private final Paint mPaintStart, mPaintEnd;` + + +--- +# Enums + +An enum type is a special data type that restricts a variable to be a set of predefined constant
s + +```java +public enum EssentialGeometry { INSIDE, OUTSIDE }; +... +EssentialGeometry where = EssentialGeometry.INSIDE; +``` +--- +# Generics + +Basically, abstraction over types +```java +Point<Integer>, Point<Double> + +// Type abstraction: abstract over element type +Interface List<E> { // Lets us use types such as: + Boolean add(E n); // List<Integer> + E get(int index); // List<String> +} // List<List<Double>> + +``` +--- +# Anonymous Inner Classes (1/3) + +In Java, Anonymous Inner Classes are inner classes (or a non-static class that’s nested inside another class) + +- Anonymous classes don’t have a name and are often used to make an instance of an object that has slightly different methods of another class or interface. +- This way, you don’t have to actually make a subclass of a class. +- You’re going to see this type of class in some of our homework when implementing something called “listeners†+ +--- +# Anonymous Inner Classes (2/3) + +```java +public class ExActivity extends AppCompatActivity { + private View.OnClickListener mClickListener = new View.OnClickListener() { + public void onClick(View v) { + if (mButton!=v) { + return; + } + } + }; // remember to end this statement with a semicolon +} + +``` +--- +# Anonymous Inner Classes (3/3) + +Digging deeper: Creating an anonymous inner class <br> +`private View.OnClickListener mClickListener = new View.OnClickListener() {` + +.left-column50[ + +`private` -- it's only available inside the class that contains it (e.g. `ExampleActivity`) + +`View.OnClickListener` -- the variable type ([Documentation](https://developer.android.com/reference/android/view/View.OnClickListener)), a nested class in `View` + +`mClickListener` is the variable name which is being set to... +] +.right-column50[ +a `new View.OnClickListener` which is an anonymous object from an abstract class +- For those of you who have not taken 331, that means there are methods that have not been implemented in the class +- The one method that you MUST implement (in order to create a new object of this type) is `onClick`, which overrides the abstract method +] +--- +# Lambdas + +What are Lambda expressions in Java? +- Block of code that can be passed around to execute +- Instances of functional interfaces +- Think of it as using code as data +- Useful for anonymous classes and functional interfaces, allows compact instances of one method classes +- This will come up later in the course when dealing with callbacks! +- Once instantiated, you can re-use it! Treat it is as a function + +--- +# Lambda Simple Example +.left-column50[ +An example functional interface +```java +interface FuncInter1 + { + int operation(int a, int b); + int multiplication(int a, int b); + } + +... + +// Implementing interface w/ lambda function +FuncInter1 add = (int x, int y) -> x + y; + + +``` +] +.right-column50[ + +You can reuse this now! +- `add.operation(2, 3)` returns 5 +- `add.multiplication(2, 3)` return 5 +] +--- +# Another Lambda Example using `::` operator + +`::` is a method reference, same as using lambda but even shorter and readable + +Syntax of `::` operator `<Class name>::<method name>` + +Lambda Example + +`numList.forEach(e -> System.out.print(e));` + +This does the same thing! + +`numList.forEach(System.out::print)` + +--- + + + + + diff --git a/docs/java/java.html b/docs/java/java.html new file mode 100644 index 0000000000000000000000000000000000000000..eddb432302a41d8567436d1eb4970c212352869d --- /dev/null +++ b/docs/java/java.html @@ -0,0 +1,404 @@ +--- +layout: presentation +title: Java Refresher +description: Java Refresher Slides +class: middle, center, inverse +--- +name: inverse +layout: true +class: center, middle, inverse +--- + +# CSE 340 ({{site.quarter}}) +## Java Refresher + +--- +layout: false + +# What is Java? + +- Strongly, statically typed language + + - Every variable has a type + - This type is decided at compile time (mostly) + +-- + +- Compiled, class-based, Object-oriented + +-- + +- Platform agnostic + + - __Write once__, _run anywhere_ without recompilation + - Especially useful for Android + +--- + +## Java Basics: Primitive Types + +-- +.left-column50[ +- Boolean + +```java +boolean hasClassStarted = true; +boolean isClassOver = false; +``` +] +--- + +## Java Basics: Primitive Types + +.left-column50[ +- Boolean + +```java +boolean hasClassStarted = true; +boolean isClassOver = false; +``` + +- Integer + +```java +int numStudents = rand.nextInt(30); +``` +] +--- + +## Java Basics: Primitive Types + +.left-column50[ +- Boolean + +```java +boolean hasClassStarted = true; +boolean isClassOver = false; +``` + +- Integer + +```java +int numStudents = rand.nextInt(30); +``` +- Float + +```java +float gradePointAverage = 3.2f; +``` +] + +-- +.right-column50[ +- Double + - Higher precision than float + +```java +double examScore = 97.362; +``` +] +-- +.right-column50[ +- Byte, Short, etc. +] +--- +## Java Basics: Text + +-- +- Characters + +```java +char section = 'B'; +``` + +-- +- Strings + +```java +String instructor = "Jennifer Mankoff"; +``` + +-- +All non-primitives types inherit from `Object` class + - Including `String`; note the capitalization + +--- +## Java Basics: Visibility Modifiers + +```java +public final String COURSE = "CSE 340"; +... +private final String SSN = "123-45-6789"; +``` + +-- +.left-column50[ +- `package private` + - This is the default access if no modifier is specified + - Accessible by all classes in the same package. +] +--- +## Java Basics: Visibility Modifiers + +```java +public final String COURSE = "CSE 340"; +... +private final String SSN = "123-45-6789"; +``` + +.left-column50[ +- `package private` + - This is the default access if no modifier is specified + - Accessible by all classes in the same package. +- `private` + - Kept secret, can only be read/written by `self` + - Cannot be accessed by subclasses +] +-- +.right-column50[ +- `protected` + - Access restricted to `self`, subclasses, and package +] +--- +## Java Basics: Visibility Modifiers + +```java +public final String COURSE = "CSE 340"; +... +private final String SSN = "123-45-6789"; +``` + +.left-column50[ +- `package private` + - This is the default access if no modifier is specified + - Accessible by all classes in the same package. +- `private` + - Kept secret, can only be read/written by `self` + - Cannot be accessed by subclasses +] +.right-column50[ +- `protected` + - Access restricted to `self`, subclasses, and package +- `public` + - The world can read/write (fields) or call (methods) +] +--- +## Java Basics: Visibility Modifiers + +-- + - Generally, you want to be as restrictive as possible + - Usually, this means `private` + +-- + + - Create getter/setter methods to modify the member variables + +-- + + - .red[__Almost never use__ `public`] for fields + - Except for constants + +--- +## Java Basics: `final` + +-- +.left-column50[ +- Prevent value from changing after initialization + +```java +// local variable cannot be modified ever! +final double courseGrade = 95.0; +``` +] +--- +## Java Basics: `final` + +.left-column50[ +- Prevent value from changing after initialization + +```java +// local variable cannot be modified ever! +final double courseGrade = 95.0; +``` + +- Prevent subclassing + +```java + // can't subclass + // (for example to make a Student class) + public final class Person { + ... + } +``` +] +-- +.right-column50[ +- Prevent overriding + +```java + // can't override! + public final int getValue() { + return 0; + } +``` +] +--- +## Java Basics: `static` + +-- +- Use for constants or variables are shared by all instances of a particular class + +```java +final static double SALES_TAX_RATE = 0.07; // Class Constant (never changes) +static double mTotalAmount = 3.56; // Class variable can change +``` + +-- +- Methods that can be called without an class instance (instantiating an object) + +```java +static String toString(int i); +// For example Integer.toString(100) => "100"; +``` + +--- +# Naming Conventions + + - class names are PascalCased + - local variables and method names are camelCased + - class or instance variables begin with a 'm' (for member), such as mTotalAmount + - constants are UPPER_SNAKE_CASED + +--- +## Java Basics: Methods +- Methods in Java typically follow this format: + +```java +{visibility} [static] [final] returnType methodName(paramType paramName, ...) { + ... +} +``` + +-- +- `static` and `final` are optional, special modifiers +- `visibility` is one of `public`, `private`, `protected`, or empty for package private + +--- +## Java Basics: Method Example + +Summing two numbers and returning the answer as a string + +```java +public String getSumOfTwoNumbersAsString(int first, int second) { + int sum = first + second; + return Integer.toString(sum); // could also return "" + sum +} +``` + +--- +## Java Basics: Declaring a class + +```Java +{visibility} class ClassName { + // Field declarations + + // Method definitions +} +``` + +--- + +## Java Basics: Constructing a Class + +```java +public class Student { + // Class (static) variables - + public static final String STUDENT_KEY = "STUDENT"; + private static final String ID_PREFIX = "S"; + + // Instance Variables + private String mIdNumber; + private String mName; + + // Constructors - used to create an instance + Student(String name, String idNumber) { + this.name = mName; + this.idNumber = mIdNumber; + } + + // Methods + public String getPrefixedIdNumber() { + return ID_PREFIX + mIdNumber; + } +``` + +--- +## Java Basics: Constructing a Class cont. +```java + // Getter + public String getName() { + return mName; + } + + // Setter + public void setName(String newName) { + if (newName == null || newName == "") { + newName = "Unknown"; + } + + mName = newName; + } + + ... // etc. + +} +``` + +--- +# Enums + +An enum type is a special data type that enables for a variable to be a set of predefined constant + +```java +public enum EssentialGeometry { INSIDE, OUTSIDE }; + +... +EssentialGeometry where = EssentialGeometry.INSIDE; +``` +--- +# Switch Statements + +A form of a conditional with different execution paths + +```java +public enum EssentialGeometry { INSIDE, ON_EDGE, OUTSIDE }; +... +EssentialGeometry where = EssentialGeometry.INSIDE; +switch (where) { + case ON_EDGE: + // do the edgy things + break; + case INSIDE: + // do the inside things but also fall through + // and do the OUTSIDE things because no break statement; + case OUTSIDE: + // do the outside things + break; + default: + // do default things + // automatically falls through +} + +``` + + +--- +## More Java Resources + +- Java Documentation (https://docs.oracle.com/en/java/javase/13/docs/api/) + +- __Online Java Practice Problems__: + + - http://codingbat.com/java + + - https://practiceit.cs.washington.edu/problem/list diff --git a/index.md b/index.md index 6966318d6449ff8e7fd56368f5920bf4e6637968..ab70b09d90d2b49f7be3e81fbc4d830f97bc79ad 100755 --- a/index.md +++ b/index.md @@ -15,8 +15,8 @@ For quick links to key things, check out the navigation bar above and the table See [Canvas]({{site.canvas}}) for all zoom meeting links -**Class Time:** \\ -**Lab Times:** +**Class Time:** M/W/F at 10:30am PDT \\ +**Lab Times:** 9:30am PDT (Section AA) and 10:30 am PDT (Section AB) # Course staff @@ -29,8 +29,8 @@ See [Canvas]({{site.canvas}}) for all zoom meeting links ## TAs :--: | :---------: | :-- | | :--: | :---------: | :-- - **Section AA** | {:class="ta-picture"} | Taylor Gotfrid (she/her) | | **Section AB** | | - **Infrastructure** | | | | | | + **Section AA** | {:class="ta-picture"} | Taylor Gotfrid (she/her) | | **Section AB** | | David Chen (he/him) + **Infrastructure** | {:class="ta-picture"} | Jeremy Zhang (he/him) | | | | # Should I take this class? @@ -326,3 +326,116 @@ Accommodations must be requested within the first two weeks of this course using [Religious Accommodations Request](https://registrar.washington.edu/students/religious-accommodations-request/) form on UW's site. +# Other relevant classes to know about + +There are a number of classes on campus that teach related concepts +which you may wish to consider in addition to this one. As of Spring 2020, +here are the ones we are aware of: + +- CSE 154: Web Programming: [Sp 20](https://courses.cs.washington.edu/courses/cse154/20sp/) + This course covers languages, tools, and techniques for developing interactive and dynamic web + pages. Topics include page styling, design, and layout; client and server side scripting; + web security; and interacting with data sources such as databases. +- [HCDE 310: Interactive Systems Design & + Technology](https://www.smunson.com/teaching/hcde310/a17/) This course is a + project based course that teaches how to prototype applications on the + web using Python that solve human problems or enable new + activities. Includes information about APIs and how people interact with them. It + differs from CSE 340 in its choice of platform. Additionally, it + doesn’t cover the theory of UI programming, nor issues such as + accessibility, undo, and so on. +- [INFO 343: Client side web + development](https://canvas.uw.edu/courses/1118282) This is a + programming course, and there will be significant overlap between the + courses, as INFO 343 also touches on event based programming, output, + and accessibility. [CSE 154: Web + Programming](https://courses.cs.washington.edu/courses/cse154/20sp/) + also covers some related + material. However, both are about programming on the web using + JavaScript instead of on Android, using Java. In addition, CSE 340 + covers more of the theory of UI programming and design, similar to + HCID 520. +- [CSE 440: Introduction to + HCI](http://courses.cs.washington.edu/courses/cse440/); [441: Advanced HCI](http://courses.cs.washington.edu/courses/cse441/) This is an advanced series of courses for undergraduate + seniors. The focus of 440 is less on programming and more broadly on + methods for designing, prototyping, and evaluating user interfaces to + computing applications, while 441 is an open ended capstone + course. These are excellent follow on courses to 340, for a student + who wants to go deeper into how to make usable, enjoyable effective + interfaces, and how to solve interesting problems with HCI. Related is + [CSE 510](http://courses.cs.washington.edu/courses/csep510/), the HCI + course for the professional masters program. +- HCID 520: User Interface Software + + Technology ([Wi 17](http://uwdata.github.io/hcid520/17wi/), [Wi 16](http://faculty.washington.edu/ajko/hcid520/) [Wi 19](https://canvas.uw.edu/courses/1256337)) + This course + teaches about user interfaces, including what they are, how they are + built, and some inventions in user interface software and + technology. There are many similarities between these classes. However HCID 520 + is only open to [MHCI+D students](https://mhcid.washington.edu/) Masters students. +- [HCID 521: Prototyping](https://canvas.uw.edu/courses/1128377/assignments/syllabus) + This class is for the [MHCI+D students](https://mhcid.washington.edu/) + only and focuses on prototyping techniques, not implementation. It + covers everything from paper prototyping to physical interfaces to 3D + printing. + +<!-- | head1 | head two | three | --> +<!-- |:-------------|:------------------|:------| --> +<!-- | OK | good swedish fish | nice | --> +<!-- | out of stock | good and plenty | nice | --> +<!-- | ok | good `oreos` | hmm | --> +<!-- | ok | good `zoute` drop | yumm | --> + +<!-- ### There's a horizontal rule below this. --> + +<!-- * * * --> + +<!-- ### Here is an unordered list: --> + +<!-- * Item foo --> +<!-- * Item bar --> +<!-- * Item baz --> +<!-- * Item zip --> + +<!-- ### And an ordered list: --> + +<!-- 1. Item one --> +<!-- 1. Item two --> +<!-- 1. Item three --> +<!-- 1. Item four --> + +<!-- ### And a nested list: --> + +<!-- - level 1 item --> +<!-- - level 2 item --> +<!-- - level 2 item --> +<!-- - level 3 item --> +<!-- - level 3 item --> +<!-- - level 1 item --> +<!-- - level 2 item --> +<!-- - level 2 item --> +<!-- - level 2 item --> +<!-- - level 1 item --> +<!-- - level 2 item --> +<!-- - level 2 item --> +<!-- - level 1 item --> + +<!-- ### Definition lists can be used with HTML syntax. --> + +<!-- <dl> --> +<!-- <dt>Name</dt> --> +<!-- <dd>Godzilla</dd> --> +<!-- <dt>Born</dt> --> +<!-- <dd>1952</dd> --> +<!-- <dt>Birthplace</dt> --> +<!-- <dd>Japan</dd> --> +<!-- <dt>Color</dt> --> +<!-- <dd>Green</dd> --> +<!-- </dl> --> + +<!-- ``` --> +<!-- Long, single-line code blocks should not wrap. They should horizontally scroll if they are too long. This line should be long enough to demonstrate this. --> +<!-- ``` --> + +<!-- ``` --> +<!-- The final element. --> +<!-- ``` -->