Skip to content

Commit 784a92d

Browse files
committed
objects-classes, ch3: adding full 'class' example, finishes chapter 3 first-draft
1 parent 45f68bf commit 784a92d

File tree

1 file changed

+140
-1
lines changed

1 file changed

+140
-1
lines changed

objects-classes/ch3.md

Lines changed: 140 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,145 @@ But it fails, as shown by the last statement in that snippet. Beware that gotcha
11381138

11391139
OK, we've laid out a bunch of disparate class features. I want to wrap up this chapter by trying to illustrate a sampling of these capabilities in a single example that's a little less basic/contrived.
11401140

1141-
// TODO
1141+
```js
1142+
class CalendarItem {
1143+
static #UNSET = Symbol("unset")
1144+
static #isUnset(v) {
1145+
return v === this.#UNSET;
1146+
}
1147+
static isSameItem(item1,item2) {
1148+
if (#ID in item1 && #ID in item2) {
1149+
return item1.#ID === item2.#ID;
1150+
}
1151+
else {
1152+
return false;
1153+
}
1154+
}
1155+
1156+
#ID = CalendarItem.#UNSET
1157+
#setID(id) {
1158+
if (CalendarItem.#isUnset(this.#ID)) {
1159+
this.#ID = id;
1160+
}
1161+
else {
1162+
throw new Error("ID is already set");
1163+
}
1164+
}
1165+
1166+
description = null
1167+
startDateTime = null
1168+
1169+
constructor() {
1170+
var id = Math.round(Math.random() * 1e9);
1171+
this.#setID(id);
1172+
}
1173+
getID() {
1174+
if (!CalendarItem.#isUnset(this.#ID)) {
1175+
return this.#ID;
1176+
}
1177+
else {
1178+
throw new Error("ID is unset");
1179+
}
1180+
}
1181+
getDateTimeStr() {
1182+
if (this.startDateTime instanceof Date) {
1183+
return this.startDateTime.toUTCString();
1184+
}
1185+
}
1186+
summary() {
1187+
console.log(`(${
1188+
this.getID()
1189+
}) ${
1190+
this.description
1191+
} at ${
1192+
this.getDateTimeStr()
1193+
}`);
1194+
}
1195+
}
1196+
1197+
class Reminder extends CalendarItem {
1198+
#complete = false
1199+
1200+
constructor(description,startDateTime) {
1201+
super();
1202+
1203+
this.description = description;
1204+
this.startDateTime = startDateTime;
1205+
}
1206+
isComplete() {
1207+
return !!this.#complete;
1208+
}
1209+
markComplete() {
1210+
this.#complete = true;
1211+
}
1212+
summary() {
1213+
if (this.isComplete()) {
1214+
console.log(`(${this.getID()}) Complete.`);
1215+
}
1216+
else {
1217+
super.summary();
1218+
}
1219+
}
1220+
}
1221+
1222+
class Meeting extends CalendarItem {
1223+
endDateTime = null
1224+
1225+
#getEndDateTimeStr() {
1226+
if (this.startDateTime instanceof Date) {
1227+
return this.endDateTime.toUTCString();
1228+
}
1229+
}
1230+
1231+
constructor(description,startDateTime,endDateTime) {
1232+
super();
1233+
1234+
this.description = description;
1235+
this.startDateTime = startDateTime;
1236+
this.endDateTime = endDateTime;
1237+
}
1238+
getDateTimeStr() {
1239+
return `${
1240+
super.getDateTimeStr()
1241+
} - ${
1242+
this.#getEndDateTimeStr()
1243+
}`;
1244+
}
1245+
}
1246+
```
1247+
1248+
Take some time to read and digest those `class` definitions. Note which of the `class` features from this chapter that you see being used.
1249+
1250+
| NOTE: |
1251+
| :--- |
1252+
| One question you may have: why didn't I move the common logic of `description` and `startDateTime` setting from both subclass constructors into the single base constructor. This is a nuanced point, but it's not my intention that `CalendarItem` ever be directly instantiated; it's what in class-oriented terms we refer to as an "abstract class". That's why I'm using `new.target` to throw an error if the `CalendarItem` class is ever directly instantiated! |
1253+
1254+
Let's now see these three classes in use:
1255+
1256+
```js
1257+
var callParents = new Reminder(
1258+
"Call parents to say hi",
1259+
new Date("July 7, 2022 11:00:00 UTC")
1260+
);
1261+
callParents.summary();
1262+
// (586380912) Call parents to say hi at Thu,
1263+
// 07 Jul 2022 11:00:00 GMT
1264+
1265+
callParents.markComplete();
1266+
callParents.summary();
1267+
// (586380912) Complete.
1268+
1269+
var interview = new Meeting(
1270+
"Job Interview: ABC Tech",
1271+
new Date("June 23, 2022 08:30:00 UTC"),
1272+
new Date("June 23, 2022 09:15:00 UTC")
1273+
);
1274+
interview.summary();
1275+
// (994337604) Job Interview: ABC Tech at Thu,
1276+
// 23 Jun 2022 08:30:00 GMT - Thu, 23 Jun 2022
1277+
// 09:15:00 GMT
1278+
```
1279+
1280+
By the way, there's probably a million different ways to structure the above code logic. I'm by no means claiming this is the *right* or *best* way to do so. As an exercise for the reader, try your hand and writing it yourself, and take note of things you did differently than my approach.
11421281

11431282
[^POLP]: *Principle of Least Privilege*, https://en.wikipedia.org/wiki/Principle_of_least_privilege, 15 July 2022.

0 commit comments

Comments
 (0)