From 24ec8f93499d0615a18a86951137238677bc03e9 Mon Sep 17 00:00:00 2001 From: borb Date: Fri, 27 Jun 2025 15:44:32 +0300 Subject: [PATCH] finish lectures 8-10 - fix code snippets - update readme --- .vscode/markdown.code-snippets | 4 +- ...ic-members-methods-and-classes-slides.html | 302 ++++++----- 10-static-members-methods-and-classes.md | 405 +++++++-------- ...heritance-and-abstract-classes-slides.html | 342 +++++++++++++ 8-inheritance-and-abstract-classes.md | 483 +++++++++--------- 9-interfaces-slides.html | 306 +++++++++++ 9-interfaces.md | 358 ++++++------- README.md | 3 + 8 files changed, 1426 insertions(+), 777 deletions(-) create mode 100644 8-inheritance-and-abstract-classes-slides.html create mode 100644 9-interfaces-slides.html diff --git a/.vscode/markdown.code-snippets b/.vscode/markdown.code-snippets index 01e8643..5429f63 100644 --- a/.vscode/markdown.code-snippets +++ b/.vscode/markdown.code-snippets @@ -68,10 +68,10 @@ }, "exercise slide" : { "scope": "markdown", - "prefix": "\"exercise invert\"", + "prefix": "exercise", "body": [ "## Exercise $0.", - "", + "", ], "description": "Exercise slide colors" }, diff --git a/10-static-members-methods-and-classes-slides.html b/10-static-members-methods-and-classes-slides.html index 0862954..bc73ff7 100644 --- a/10-static-members-methods-and-classes-slides.html +++ b/10-static-members-methods-and-classes-slides.html @@ -1,4 +1,4 @@ -
+ /* content:""; */display:table}div#\:\$p>svg>foreignObject>section:after{clear:both}div#\:\$p>svg>foreignObject>section>:first-child{margin-top:0!important}div#\:\$p>svg>foreignObject>section>:last-child{margin-bottom:0!important}div#\:\$p>svg>foreignObject>section a:not([href]){color:inherit;text-decoration:none}div#\:\$p>svg>foreignObject>section .absent{color:var(--color-danger-fg)}div#\:\$p>svg>foreignObject>section .anchor{float:left;line-height:1;margin-left:-20px;padding-right:4px}div#\:\$p>svg>foreignObject>section .anchor:focus{outline:none}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre),div#\:\$p>svg>foreignObject>section blockquote,div#\:\$p>svg>foreignObject>section details,div#\:\$p>svg>foreignObject>section dl,div#\:\$p>svg>foreignObject>section ol,div#\:\$p>svg>foreignObject>section p,div#\:\$p>svg>foreignObject>section table,div#\:\$p>svg>foreignObject>section ul{margin-bottom:16px;margin-top:0}div#\:\$p>svg>foreignObject>section blockquote>:first-child{margin-top:0}div#\:\$p>svg>foreignObject>section blockquote>:last-child{margin-bottom:0}div#\:\$p>svg>foreignObject>section :is(h1,marp-h1) .octicon-link,div#\:\$p>svg>foreignObject>section :is(h2,marp-h2) .octicon-link,div#\:\$p>svg>foreignObject>section :is(h3,marp-h3) .octicon-link,div#\:\$p>svg>foreignObject>section :is(h4,marp-h4) .octicon-link,div#\:\$p>svg>foreignObject>section :is(h5,marp-h5) .octicon-link,div#\:\$p>svg>foreignObject>section :is(h6,marp-h6) .octicon-link{color:var(--color-fg-default);vertical-align:middle;visibility:hidden}div#\:\$p>svg>foreignObject>section :is(h1,marp-h1):hover .anchor,div#\:\$p>svg>foreignObject>section :is(h2,marp-h2):hover .anchor,div#\:\$p>svg>foreignObject>section :is(h3,marp-h3):hover .anchor,div#\:\$p>svg>foreignObject>section :is(h4,marp-h4):hover .anchor,div#\:\$p>svg>foreignObject>section :is(h5,marp-h5):hover .anchor,div#\:\$p>svg>foreignObject>section :is(h6,marp-h6):hover .anchor{text-decoration:none}div#\:\$p>svg>foreignObject>section :is(h1,marp-h1):hover .anchor .octicon-link,div#\:\$p>svg>foreignObject>section :is(h2,marp-h2):hover .anchor .octicon-link,div#\:\$p>svg>foreignObject>section :is(h3,marp-h3):hover .anchor .octicon-link,div#\:\$p>svg>foreignObject>section :is(h4,marp-h4):hover .anchor .octicon-link,div#\:\$p>svg>foreignObject>section :is(h5,marp-h5):hover .anchor .octicon-link,div#\:\$p>svg>foreignObject>section :is(h6,marp-h6):hover .anchor .octicon-link{visibility:visible}div#\:\$p>svg>foreignObject>section :is(h1,marp-h1) code,div#\:\$p>svg>foreignObject>section :is(h1,marp-h1) tt,div#\:\$p>svg>foreignObject>section :is(h2,marp-h2) code,div#\:\$p>svg>foreignObject>section :is(h2,marp-h2) tt,div#\:\$p>svg>foreignObject>section :is(h3,marp-h3) code,div#\:\$p>svg>foreignObject>section :is(h3,marp-h3) tt,div#\:\$p>svg>foreignObject>section :is(h4,marp-h4) code,div#\:\$p>svg>foreignObject>section :is(h4,marp-h4) tt,div#\:\$p>svg>foreignObject>section :is(h5,marp-h5) code,div#\:\$p>svg>foreignObject>section :is(h5,marp-h5) tt,div#\:\$p>svg>foreignObject>section :is(h6,marp-h6) code,div#\:\$p>svg>foreignObject>section :is(h6,marp-h6) tt{font-size:inherit;padding:0 .2em}div#\:\$p>svg>foreignObject>section summary :is(h1,marp-h1),div#\:\$p>svg>foreignObject>section summary :is(h2,marp-h2),div#\:\$p>svg>foreignObject>section summary :is(h3,marp-h3),div#\:\$p>svg>foreignObject>section summary :is(h4,marp-h4),div#\:\$p>svg>foreignObject>section summary :is(h5,marp-h5),div#\:\$p>svg>foreignObject>section summary :is(h6,marp-h6){display:inline-block}div#\:\$p>svg>foreignObject>section summary :is(h1,marp-h1) .anchor,div#\:\$p>svg>foreignObject>section summary :is(h2,marp-h2) .anchor,div#\:\$p>svg>foreignObject>section summary :is(h3,marp-h3) .anchor,div#\:\$p>svg>foreignObject>section summary :is(h4,marp-h4) .anchor,div#\:\$p>svg>foreignObject>section summary :is(h5,marp-h5) .anchor,div#\:\$p>svg>foreignObject>section summary :is(h6,marp-h6) .anchor{margin-left:-40px}div#\:\$p>svg>foreignObject>section summary :is(h1,marp-h1),div#\:\$p>svg>foreignObject>section summary :is(h2,marp-h2){border-bottom:0;padding-bottom:0}div#\:\$p>svg>foreignObject>section ol.no-list,div#\:\$p>svg>foreignObject>section ul.no-list{list-style-type:none;padding:0}div#\:\$p>svg>foreignObject>section ol[type="a s"]{list-style-type:lower-alpha}div#\:\$p>svg>foreignObject>section ol[type="A s"]{list-style-type:upper-alpha}div#\:\$p>svg>foreignObject>section ol[type="i s"]{list-style-type:lower-roman}div#\:\$p>svg>foreignObject>section ol[type="I s"]{list-style-type:upper-roman}div#\:\$p>svg>foreignObject>section div>ol:not([type]),div#\:\$p>svg>foreignObject>section ol[type="1"]{list-style-type:decimal}div#\:\$p>svg>foreignObject>section ol ol,div#\:\$p>svg>foreignObject>section ol ul,div#\:\$p>svg>foreignObject>section ul ol,div#\:\$p>svg>foreignObject>section ul ul{margin-bottom:0;margin-top:0}div#\:\$p>svg>foreignObject>section li>p{margin-top:16px}div#\:\$p>svg>foreignObject>section li+li{margin-top:.25em}div#\:\$p>svg>foreignObject>section dl{padding:0}div#\:\$p>svg>foreignObject>section dl dt{font-size:1em;font-style:italic;font-weight:var(--base-text-weight-semibold,600);margin-top:16px;padding:0}div#\:\$p>svg>foreignObject>section dl dd{margin-bottom:16px;padding:0 16px}div#\:\$p>svg>foreignObject>section table th{font-weight:var(--base-text-weight-semibold,600)}div#\:\$p>svg>foreignObject>section table td,div#\:\$p>svg>foreignObject>section table th{border:1px solid var(--color-border-default);padding:6px 13px}div#\:\$p>svg>foreignObject>section table td>:last-child{margin-bottom:0}div#\:\$p>svg>foreignObject>section table tr{background-color:var(--color-canvas-default);border-top:1px solid var(--color-border-muted)}div#\:\$p>svg>foreignObject>section table tr:nth-child(2n){background-color:var(--color-canvas-subtle)}div#\:\$p>svg>foreignObject>section table img{background-color:transparent}div#\:\$p>svg>foreignObject>section img[align=right]{padding-left:20px}div#\:\$p>svg>foreignObject>section img[align=left]{padding-right:20px}div#\:\$p>svg>foreignObject>section .emoji{background-color:transparent;max-width:none;vertical-align:text-top}div#\:\$p>svg>foreignObject>section :is(span,marp-span).frame,div#\:\$p>svg>foreignObject>section :is(span,marp-span).frame>:is(span,marp-span){display:block;overflow:hidden}div#\:\$p>svg>foreignObject>section :is(span,marp-span).frame>:is(span,marp-span){border:1px solid var(--color-border-default);float:left;margin:13px 0 0;padding:7px;width:auto}div#\:\$p>svg>foreignObject>section :is(span,marp-span).frame :is(span,marp-span) img{display:block;float:left}div#\:\$p>svg>foreignObject>section :is(span,marp-span).frame :is(span,marp-span) :is(span,marp-span){clear:both;color:var(--color-fg-default);display:block;padding:5px 0 0}div#\:\$p>svg>foreignObject>section :is(span,marp-span).align-center{clear:both;display:block;overflow:hidden}div#\:\$p>svg>foreignObject>section :is(span,marp-span).align-center>:is(span,marp-span){display:block;margin:13px auto 0;overflow:hidden;text-align:center}div#\:\$p>svg>foreignObject>section :is(span,marp-span).align-center :is(span,marp-span) img{margin:0 auto;text-align:center}div#\:\$p>svg>foreignObject>section :is(span,marp-span).align-right{clear:both;display:block;overflow:hidden}div#\:\$p>svg>foreignObject>section :is(span,marp-span).align-right>:is(span,marp-span){display:block;margin:13px 0 0;overflow:hidden;text-align:right}div#\:\$p>svg>foreignObject>section :is(span,marp-span).align-right :is(span,marp-span) img{margin:0;text-align:right}div#\:\$p>svg>foreignObject>section :is(span,marp-span).float-left{display:block;float:left;margin-right:13px;overflow:hidden}div#\:\$p>svg>foreignObject>section :is(span,marp-span).float-left :is(span,marp-span){margin:13px 0 0}div#\:\$p>svg>foreignObject>section :is(span,marp-span).float-right{display:block;float:right;margin-left:13px;overflow:hidden}div#\:\$p>svg>foreignObject>section :is(span,marp-span).float-right>:is(span,marp-span){display:block;margin:13px auto 0;overflow:hidden;text-align:right}div#\:\$p>svg>foreignObject>section code,div#\:\$p>svg>foreignObject>section tt{background-color:var(--color-neutral-muted);border-radius:6px;font-size:85%;margin:0;padding:.2em .4em;white-space:break-spaces}div#\:\$p>svg>foreignObject>section code br,div#\:\$p>svg>foreignObject>section tt br{display:none}div#\:\$p>svg>foreignObject>section del code{text-decoration:inherit}div#\:\$p>svg>foreignObject>section samp{font-size:85%}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) code{font-size:100%}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre)>code{background:transparent;border:0;margin:0;padding:0;white-space:pre;word-break:normal}div#\:\$p>svg>foreignObject>section .highlight{margin-bottom:16px}div#\:\$p>svg>foreignObject>section .highlight :is(pre,marp-pre){margin-bottom:0;word-break:normal}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre){background-color:var(--color-canvas-subtle);border-radius:6px;color:var(--color-fg-default);font-size:85%;line-height:1.45;overflow:auto;padding:16px}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) code,div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) tt{word-wrap:normal;background-color:transparent;border:0;display:inline;line-height:inherit;margin:0;max-width:auto;overflow:visible;padding:0}div#\:\$p>svg>foreignObject>section .csv-data td,div#\:\$p>svg>foreignObject>section .csv-data th{font-size:12px;line-height:1;overflow:hidden;padding:5px;text-align:left;white-space:nowrap}div#\:\$p>svg>foreignObject>section .csv-data .blob-num{background:var(--color-canvas-default);border:0;padding:10px 8px 9px;text-align:right}div#\:\$p>svg>foreignObject>section .csv-data tr{border-top:0}div#\:\$p>svg>foreignObject>section .csv-data th{background:var(--color-canvas-subtle);border-top:0;font-weight:var(--base-text-weight-semibold,600)}div#\:\$p>svg>foreignObject>section [data-footnote-ref]:before{content:"["}div#\:\$p>svg>foreignObject>section [data-footnote-ref]:after{content:"]"}div#\:\$p>svg>foreignObject>section .footnotes{border-top:1px solid var(--color-border-default);color:var(--color-fg-muted);font-size:12px}div#\:\$p>svg>foreignObject>section div#\:\$p>svg>foreignObject>section section.footnotes{--marpit-root-font-size:12px}div#\:\$p>svg>foreignObject>section .footnotes ol{padding-left:16px}div#\:\$p>svg>foreignObject>section .footnotes ol ul{display:inline-block;margin-top:16px;padding-left:16px}div#\:\$p>svg>foreignObject>section .footnotes li{position:relative}div#\:\$p>svg>foreignObject>section .footnotes li:target:before{border:2px solid var(--color-accent-emphasis);border-radius:6px;bottom:-8px;content:"";left:-24px;pointer-events:none;position:absolute;right:-8px;top:-8px}div#\:\$p>svg>foreignObject>section .footnotes li:target{color:var(--color-fg-default)}div#\:\$p>svg>foreignObject>section .footnotes .data-footnote-backref g-emoji{font-family:monospace}div#\:\$p>svg>foreignObject>section .pl-c{color:var(--color-prettylights-syntax-comment)}div#\:\$p>svg>foreignObject>section .pl-c1,div#\:\$p>svg>foreignObject>section .pl-s .pl-v{color:var(--color-prettylights-syntax-constant)}div#\:\$p>svg>foreignObject>section .pl-e,div#\:\$p>svg>foreignObject>section .pl-en{color:var(--color-prettylights-syntax-entity)}div#\:\$p>svg>foreignObject>section .pl-s .pl-s1,div#\:\$p>svg>foreignObject>section .pl-smi{color:var(--color-prettylights-syntax-storage-modifier-import)}div#\:\$p>svg>foreignObject>section .pl-ent{color:var(--color-prettylights-syntax-entity-tag)}div#\:\$p>svg>foreignObject>section .pl-k{color:var(--color-prettylights-syntax-keyword)}div#\:\$p>svg>foreignObject>section .pl-pds,div#\:\$p>svg>foreignObject>section .pl-s,div#\:\$p>svg>foreignObject>section .pl-s .pl-pse .pl-s1,div#\:\$p>svg>foreignObject>section .pl-sr,div#\:\$p>svg>foreignObject>section .pl-sr .pl-cce,div#\:\$p>svg>foreignObject>section .pl-sr .pl-sra,div#\:\$p>svg>foreignObject>section .pl-sr .pl-sre{color:var(--color-prettylights-syntax-string)}div#\:\$p>svg>foreignObject>section .pl-smw,div#\:\$p>svg>foreignObject>section .pl-v{color:var(--color-prettylights-syntax-variable)}div#\:\$p>svg>foreignObject>section .pl-bu{color:var(--color-prettylights-syntax-brackethighlighter-unmatched)}div#\:\$p>svg>foreignObject>section .pl-ii{background-color:var(--color-prettylights-syntax-invalid-illegal-bg);color:var(--color-prettylights-syntax-invalid-illegal-text)}div#\:\$p>svg>foreignObject>section .pl-c2{background-color:var(--color-prettylights-syntax-carriage-return-bg);color:var(--color-prettylights-syntax-carriage-return-text)}div#\:\$p>svg>foreignObject>section .pl-sr .pl-cce{color:var(--color-prettylights-syntax-string-regexp);font-weight:700}div#\:\$p>svg>foreignObject>section .pl-ml{color:var(--color-prettylights-syntax-markup-list)}div#\:\$p>svg>foreignObject>section .pl-mh,div#\:\$p>svg>foreignObject>section .pl-mh .pl-en,div#\:\$p>svg>foreignObject>section .pl-ms{color:var(--color-prettylights-syntax-markup-heading);font-weight:700}div#\:\$p>svg>foreignObject>section .pl-mi{color:var(--color-prettylights-syntax-markup-italic);font-style:italic}div#\:\$p>svg>foreignObject>section .pl-mb{color:var(--color-prettylights-syntax-markup-bold);font-weight:700}div#\:\$p>svg>foreignObject>section .pl-md{background-color:var(--color-prettylights-syntax-markup-deleted-bg);color:var(--color-prettylights-syntax-markup-deleted-text)}div#\:\$p>svg>foreignObject>section .pl-mi1{background-color:var(--color-prettylights-syntax-markup-inserted-bg);color:var(--color-prettylights-syntax-markup-inserted-text)}div#\:\$p>svg>foreignObject>section .pl-mc{background-color:var(--color-prettylights-syntax-markup-changed-bg);color:var(--color-prettylights-syntax-markup-changed-text)}div#\:\$p>svg>foreignObject>section .pl-mi2{background-color:var(--color-prettylights-syntax-markup-ignored-bg);color:var(--color-prettylights-syntax-markup-ignored-text)}div#\:\$p>svg>foreignObject>section .pl-mdr{color:var(--color-prettylights-syntax-meta-diff-range);font-weight:700}div#\:\$p>svg>foreignObject>section .pl-ba{color:var(--color-prettylights-syntax-brackethighlighter-angle)}div#\:\$p>svg>foreignObject>section .pl-sg{color:var(--color-prettylights-syntax-sublimelinter-gutter-mark)}div#\:\$p>svg>foreignObject>section .pl-corl{color:var(--color-prettylights-syntax-constant-other-reference-link);text-decoration:underline}div#\:\$p>svg>foreignObject>section g-emoji{display:inline-block;font-family:Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;font-size:1em;font-style:normal!important;font-weight:var(--base-text-weight-normal,400);line-height:1;min-width:1ch;vertical-align:-.075em}div#\:\$p>svg>foreignObject>section g-emoji img{height:1em;width:1em}div#\:\$p>svg>foreignObject>section .task-list-item{list-style-type:none}div#\:\$p>svg>foreignObject>section .task-list-item label{font-weight:var(--base-text-weight-normal,400)}div#\:\$p>svg>foreignObject>section .task-list-item.enabled label{cursor:pointer}div#\:\$p>svg>foreignObject>section .task-list-item+.task-list-item{margin-top:4px}div#\:\$p>svg>foreignObject>section .task-list-item .handle{display:none}div#\:\$p>svg>foreignObject>section .task-list-item-checkbox{margin:0 .2em .25em -1.4em;vertical-align:middle}div#\:\$p>svg>foreignObject>section .contains-task-list:dir(rtl) .task-list-item-checkbox{margin:0 -1.6em .25em .2em}div#\:\$p>svg>foreignObject>section .contains-task-list{position:relative}div#\:\$p>svg>foreignObject>section .contains-task-list:focus-within .task-list-item-convert-container,div#\:\$p>svg>foreignObject>section .contains-task-list:hover .task-list-item-convert-container{clip:auto;display:block;height:24px;overflow:visible;width:auto}div#\:\$p>svg>foreignObject>section ::-webkit-calendar-picker-indicator{filter:invert(50%)}div#\:\$p>svg>foreignObject>section :is(h1,marp-h1){color:var(--h1-color);font-size:1.6em}div#\:\$p>svg>foreignObject>section :is(h1,marp-h1),div#\:\$p>svg>foreignObject>section :is(h2,marp-h2){border-bottom:none}div#\:\$p>svg>foreignObject>section :is(h2,marp-h2){font-size:1.3em}div#\:\$p>svg>foreignObject>section :is(h3,marp-h3){font-size:1.1em}div#\:\$p>svg>foreignObject>section :is(h4,marp-h4){font-size:1.05em}div#\:\$p>svg>foreignObject>section :is(h5,marp-h5){font-size:1em}div#\:\$p>svg>foreignObject>section :is(h6,marp-h6){font-size:.9em}div#\:\$p>svg>foreignObject>section :is(h1,marp-h1) strong,div#\:\$p>svg>foreignObject>section :is(h2,marp-h2) strong,div#\:\$p>svg>foreignObject>section :is(h3,marp-h3) strong,div#\:\$p>svg>foreignObject>section :is(h4,marp-h4) strong,div#\:\$p>svg>foreignObject>section :is(h5,marp-h5) strong,div#\:\$p>svg>foreignObject>section :is(h6,marp-h6) strong{color:var(--heading-strong-color);font-weight:inherit}div#\:\$p>svg>foreignObject>section :is(h1,marp-h1)::part(auto-scaling),div#\:\$p>svg>foreignObject>section :is(h2,marp-h2)::part(auto-scaling),div#\:\$p>svg>foreignObject>section :is(h3,marp-h3)::part(auto-scaling),div#\:\$p>svg>foreignObject>section :is(h4,marp-h4)::part(auto-scaling),div#\:\$p>svg>foreignObject>section :is(h5,marp-h5)::part(auto-scaling),div#\:\$p>svg>foreignObject>section :is(h6,marp-h6)::part(auto-scaling){max-height:563px}div#\:\$p>svg>foreignObject>section hr{height:0;padding-top:.25em}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre){border:1px solid var(--color-border-default);line-height:1.15;overflow:visible}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre)::part(auto-scaling){max-height:529px}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs){color:var(--color-prettylights-syntax-storage-modifier-import)}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-doctag),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-keyword),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-meta .hljs-keyword),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-template-tag),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-template-variable),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-type),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-variable.language_){color:var(--color-prettylights-syntax-keyword)}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-title),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-title.class_),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-title.class_.inherited__),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-title.function_){color:var(--color-prettylights-syntax-entity)}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-attr),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-attribute),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-literal),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-meta),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-number),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-operator),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-selector-attr),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-selector-class),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-selector-id),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-variable){color:var(--color-prettylights-syntax-constant)}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-meta .hljs-string),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-regexp),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-string){color:var(--color-prettylights-syntax-string)}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-built_in),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-symbol){color:var(--color-prettylights-syntax-variable)}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-code),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-comment),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-formula){color:var(--color-prettylights-syntax-comment)}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-name),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-quote),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-selector-pseudo),div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-selector-tag){color:var(--color-prettylights-syntax-entity-tag)}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-subst){color:var(--color-prettylights-syntax-storage-modifier-import)}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-section){color:var(--color-prettylights-syntax-markup-heading);font-weight:700}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-bullet){color:var(--color-prettylights-syntax-markup-list)}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-emphasis){color:var(--color-prettylights-syntax-markup-italic);font-style:italic}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-strong){color:var(--color-prettylights-syntax-markup-bold);font-weight:700}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-addition){background-color:var(--color-prettylights-syntax-markup-inserted-bg);color:var(--color-prettylights-syntax-markup-inserted-text)}div#\:\$p>svg>foreignObject>section :is(pre,marp-pre) :where(.hljs-deletion){background-color:var(--color-prettylights-syntax-markup-deleted-bg);color:var(--color-prettylights-syntax-markup-deleted-text)}div#\:\$p>svg>foreignObject>section footer,div#\:\$p>svg>foreignObject>section header{color:var(--header-footer-color);font-size:18px;left:30px;margin:0;position:absolute}div#\:\$p>svg>foreignObject>section header{top:21px}div#\:\$p>svg>foreignObject>section footer{bottom:21px}div#\:\$p>svg>foreignObject>section{--h1-color:#246;--header-footer-color:hsla(0,0%,40%,.75);--heading-strong-color:#48c;--paginate-color:#777;align-items:stretch;display:flex;flex-flow:column nowrap;font-size:29px;height:720px;justify-content:center;padding:78.5px;width:1280px}div#\:\$p>svg>foreignObject>section{--marpit-root-font-size:29px}div#\:\$p>svg>foreignObject>section:where(.invert){--h1-color:#cee7ff;--header-footer-color:hsla(0,0%,60%,.75);--heading-strong-color:#7bf;--paginate-color:#999}div#\:\$p>svg>foreignObject>section>:last-child,div#\:\$p>svg>foreignObject>section[data-footer]>:nth-last-child(2){margin-bottom:0}div#\:\$p>svg>foreignObject>section>:first-child,div#\:\$p>svg>foreignObject>section>header:first-child+*{margin-top:0}div#\:\$p>svg>foreignObject>section:after{bottom:21px;color:var(--paginate-color);font-size:24px;padding:0;position:absolute;right:30px}div#\:\$p>svg>foreignObject>section:after{--marpit-root-font-size:24px}div#\:\$p>svg>foreignObject>section[data-color] :is(h1,marp-h1),div#\:\$p>svg>foreignObject>section[data-color] :is(h2,marp-h2),div#\:\$p>svg>foreignObject>section[data-color] :is(h3,marp-h3),div#\:\$p>svg>foreignObject>section[data-color] :is(h4,marp-h4),div#\:\$p>svg>foreignObject>section[data-color] :is(h5,marp-h5),div#\:\$p>svg>foreignObject>section[data-color] :is(h6,marp-h6){color:currentcolor}div#\:\$p>svg>foreignObject>:where(section){container-type:size}div#\:\$p>svg>foreignObject>section img[data-marp-twemoji]{background:transparent;height:1em;margin:0 .05em 0 .1em;vertical-align:-.1em;width:1em} +/* buutti.css */ +/* @theme buutti */div#\:\$p>svg>foreignObject>section .columns{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .columns12{display:grid;grid-template-columns:1fr 2fr;gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .columns21{display:grid;grid-template-columns:2fr 1fr;gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .columns32{display:grid;grid-template-columns:3fr 2fr;gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .columns23{display:grid;grid-template-columns:2fr 3fr;gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .columns111{display:grid;grid-template-columns:1fr 1fr 1fr;gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .centered{display:flex;flex-direction:column;justify-content:center;text-align:center}div#\:\$p>svg>foreignObject>section .tableborderless td,div#\:\$p>svg>foreignObject>section th{border:none!important;border-collapse:collapse}div#\:\$p>svg>foreignObject>section.extra{background-color:#5d275d;background-image:linear-gradient(to bottom,#401a40,#1d0c1d);color:white}div#\:\$p>svg>foreignObject>section.extra a{color:rgb(145,255,209)}div#\:\$p>svg>foreignObject>section.exercise{background-color:#29366f;background-image:linear-gradient(to bottom,#20636a,#173742);color:white}div#\:\$p>svg>foreignObject>section.exercise a{color:rgb(211,173,255)} + +/* @theme fa5agneqe2xxbat58gzzfpwqzuczahqrysq4tolfj */div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]{columns:initial!important;display:block!important;padding:0!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:before,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:before{display:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]{all:initial;display:flex;flex-direction:row;height:100%;overflow:hidden;width:100%}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container][data-marpit-advanced-background-direction=vertical]{flex-direction:column}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split]>div[data-marpit-advanced-background-container]{width:var(--marpit-advanced-background-split,50%)}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split=right]>div[data-marpit-advanced-background-container]{margin-left:calc(100% - var(--marpit-advanced-background-split, 50%))}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure{all:initial;background-position:center;background-repeat:no-repeat;background-size:cover;flex:auto;margin:0}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure>figcaption{position:absolute;border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;white-space:nowrap;width:1px}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content],div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo]{background:transparent!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo],div#\:\$p>svg[data-marpit-svg]>foreignObject[data-marpit-advanced-background=pseudo]{pointer-events:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background-split]{width:100%;height:100%}

Static Members, Methods and Classes

-

-
-

Static Members

-

So far, we have used non-static fields in our classes

-

This means, that each instance of the class holds its own version of the field, and changing the value of it only affects that instance:

-

class MyAwesomeClass

-

{

-

public int MyProperty { get; set; }

-

}

-

class Program

-

{

-

static void Main(string[] args)

-

{

-

MyAwesomeClass instance1 = new MyAwesomeClass();

-

MyAwesomeClass instance2 = new MyAwesomeClass();

-

instance1.MyProperty = 100;

-

instance2.MyProperty = 200; // instance1.MyProperty is still 100

-

}

-

}

-

Static Members (continued)

-

Likewise, non-static class methods _have to _ be called through an instance:

-

class MyAwesomeClass

-

{

-

public void PrintText(string text) { Console.WriteLine(text); }

-

}

-

class Program

-

{

-

static void Main(string[] args)

-

{

-

MyAwesomeClass instance = new MyAwesomeClass();

-

instance.PrintText("Hello World"); // Outputs "Hello World"

-

MyAwesomeClass.PrintText("Hello World"); // Results in an error

-

}

-

}

-

-

Static fields are shared between all instances of a class

-

Let's declare "MyProperty" property with the __static __ keyword. Now it can be referenced through the class type name, but not through the instance, as shown below:

-

class MyAwesomeClass

-

{

-

public static int MyProperty { get; set; } = 100;

-

}

-

class Program

-

{

-

static void Main(string[] args)

-

{

-

MyAwesomeClass instance = new MyAwesomeClass();

-

Console.WriteLine(MyAwesomeClass.MyProperty); // Outputs "100"

-

Console.WriteLine(instance.MyProperty); // Results in an error

-

}

-

}

-

-

Static Members - Example

-

In this example, a static field is used for keeping count on how many times the class has been instantiated:

-

class Person

-

{

-

public static int totalPersons = 0;

-

private string name;

-

public Person(string personName) // Person Constructor

-

{

-

name = personName;

-

++totalPersons;

-

}

-

public void PrintInfo()

-

{

-

Console.WriteLine("This person is called " + name + ".");

-

Console.WriteLine("There are " + totalPersons + " persons total.");

-

}

-

}

-

Static Members - Example (continued)

-

Now let's instantiate a couple of persons and print their info:

-

class Program

-

{

-

static void Main(string[] args)

-

{

-

Person steve = new Person("Steve");

-

Person wendy = new Person("Wendy");

-

steve.PrintInfo();

-

wendy.PrintInfo();

-

}

-

}

-

-

Static Methods

-

Methods can also be static

-

What happens when you try to call a non-static method from a static method?

-

class Program

-

{

-

void PrintHelloName(string name)

-

{

-

Console.WriteLine("Hello, " + name);

-

}

-

static void Main(string[] args)

-

{

-

PrintHelloName(); // Will throw an error

-

}

-

}

-

+
+

Static Members

-
-

This is why until this point all example methods have been inside of the main function

-

Static Classes

+
+

Non-static members

    -
  • Classes can also be made static +
  • So far, we have used non-static fields in our classes
  • +
  • Meaning that each instance of the class holds its own version of the field, and changing the value of it only affects that instance:
    class MyAwesomeClass
    +{
    +  public int MyProperty { get; set; }
    +}
    +class Program
    +{
    +  static void Main(string[] args)
    +  {
    +    MyAwesomeClass instance1 = new MyAwesomeClass();
    +    MyAwesomeClass instance2 = new MyAwesomeClass();
    +    instance1.MyProperty = 100;
    +    instance2.MyProperty = 200;     // instance1.MyProperty is still 100
    +  }
    +}
    +
    +
  • +
+
+
    -
  • Static classes cannot be instantiated
  • -
  • All members of a static class also have to be static
  • +
  • Likewise, non-static class methods have to be called through an instance:
    class MyAwesomeClass
    +{
    +  public void PrintText(string text)
    +  {
    +    Console.WriteLine(text);
    +  }
    +}
    +class Program
    +{
    +  static void Main(string[] args)
    +  {
    +    MyAwesomeClass instance = new MyAwesomeClass();
    +    instance.PrintText("Hello World");          // Outputs "Hello World"
    +    MyAwesomeClass.PrintText("Hello World");    // Results in an error
    +  }
    +}
    +
    +
+
+

+
+
+
+

Static members

+
    +
  • Let's declare a property MyProperty with the static keyword
  • +
  • It can be referenced through the class, but not through the instance:
    class MyAwesomeClass
    +{
    +  public static int MyProperty { get; set; } = 100;
    +}
    +class Program
    +{
    +  static void Main(string[] args)
    +  {
    +    MyAwesomeClass instance = new MyAwesomeClass();
    +    Console.WriteLine(MyAwesomeClass.MyProperty); 	// Outputs "100"
    +    Console.WriteLine(instance.MyProperty);       	// Results in an error
    +  }
    +}
    +
    +
  • +
+
+

+
+
+
+

Static members: An example

+
    +
  • In this example, a static field is used for keeping count on how many times the class has been instantiated:
    class Person
    +{
    +  public static int totalPersons = 0;
    +  private string name;
    +  public Person(string personName)	// Person Constructor
    +  {
    +    name = personName;
    +    ++totalPersons;
    +  }
    +  public void PrintInfo()
    +  {
    +    Console.WriteLine("This person is called " + name + ".");
    +    Console.WriteLine("There are " + totalPersons + " persons total.");
    +  }
    +}
    +
    +
  • +
+
+
+
    +
  • Now let's instantiate a couple of persons and print their info:
  • +
+
+
+
class Program
+{
+  static void Main(string[] args)
+  {
+    Person steve = new Person("Steve");
+    Person wendy = new Person("Wendy");
+    steve.PrintInfo();
+    wendy.PrintInfo();
+  }
+}
+
+
+
+

+
+
+
+
+

Static methods

+
    +
  • Methods can also be static
  • +
  • What happens when you try to call a non-static method from a static method?
    class Program
    +{
    +  void PrintHelloName(string name)
    +  {
    +    Console.WriteLine("Hello, " + name);
    +  }
    +  static void Main(string[] args)
    +  {
    +    PrintHelloName();   // Will throw an error
    +  }
    +}
    +
    +
  • +
+
+

+
+
+
+

Static classes

+
    +
  • Whole classes can also be static
  • +
  • Static classes cannot be instantiated, and all its members have to be static as well
    static class Styling
    +{
    +  public static string fontFamily = "Verdana";
    +  public static float fontSize = 12.5f;
    +}
    +class Program
    +{
    +  static void Main(string[] args)
    +  {
    +    Console.WriteLine
    +      ("Using font " + Styling.fontFamily + " " + Styling.fontSize + "px");
    +    // Outputs "Using font Verdana 12.5px"
    +    Styling = new Styling();    // Results in an error
    +  }
    +}
    +
    +
  • +
+
+
+

Exercise 1

+ +
    +
  • Create a class Message that has two static properties int TotalMessages and string LastMessage, and a non-static property string MessageText.
  • +
  • Add a constructor that takes a string message as a parameter, increases TotalMessages by one and sets the value of LastMessage to message.
  • +
  • Create a main loop that keeps asking the user for a new message. A new Message instance is then created with the user input message as an argument:
    Message newMessage = new Message(message);
    +
  • -
  • static class Styling
  • -
  • {
  • -
  • public static string fontFamily = "Verdana";
  • -
  • public static float fontSize = 12.5f;
  • -
  • }
  • -
  • class Program
  • -
  • {
  • -
  • static void Main(string[] args)
  • -
  • {
  • -
  • Console.WriteLine
  • -
  • ("Using font " + Styling.fontFamily + " " + Styling.fontSize + "px");
  • -
  • // Outputs "Using font Verdana 12.5px"
  • -
  • Styling = new Styling(); // Results in an error
  • -
  • }
  • -
  • }
  • +
  • newMessage is then added to a list allMessages.
  • +
  • Finally, the static values Message.TotalMessages and Message.LastMessage are printed.
-

Exercise 1

-

Create a class Message which has two __static __ properties int TotalMessages and string LastMessage, and a __non-static __ property string MessageText.

-

Add a constructor which takes a string message as a parameter, increases TotalMessages by one and sets the value of LastMessage to message which is the parameter

-

Create a main loop which keeps asking the user for a new message. A new Message instance is then created with the user input message as an argument:

-

Message newMessage = new Message(message);

-

newMessage is then added to a list of messages, allMessages

-

Finally the static values Message.TotalMessages and Message.LastMessage are printed

\ No newline at end of file diff --git a/8-inheritance-and-abstract-classes.md b/8-inheritance-and-abstract-classes.md index 84ca60d..52fe1d8 100644 --- a/8-inheritance-and-abstract-classes.md +++ b/8-inheritance-and-abstract-classes.md @@ -1,302 +1,307 @@ -# Inheritance & Abstract Classes - -![](imgs/8%20Inheritance%20%26%20Abstract%20Classes_0.png) - +--- +marp: true +paginate: true +math: mathjax +theme: buutti +title: 8. Inheritance & Abstract Classes --- -# Overview - -Inheritance - -Abstract Classes +# Inheritance & Abstract Classes -Enums + + -# Inheritance +## Overview -Classes can be made to inherit functionality of some other class +* Inheritance +* Abstract classes +* Enums +* OOP -If class B inherits class A, all of the (public) functionality in class A is also available in class B +## Inheritance -A is called the __base class__ (or parent class) and B is called the __derived class __ (or child class) +* Classes can be made to inherit functionality of some other class +* If class B inherits class A, all of the (public) functionality in class A is also available in class B +* A is called the *__base class__* (or parent class) and B is called the *__derived class__* (or child class) +* Use the `:` symbol to make a class inherit from another -Use the " __:"__ symbol to make a class inherit from another +### An inheritance example -Try to understand the following example: +
-| class Animal | -| :-: | -| -Eat()-Sleep() | +| `class Animal` | `class Dog : Animal` | `class Cat : Animal` | +|:--------------:|:--------------------:|:--------------------:| +| `Eat()` | `Bark()` | `Meow()` | +| `Sleep()` | | | -| class Dog : Animal | -| :-: | -| -Bark() | +
-| class Cat : Animal | -| :-: | -| -Meow() | +
-Animal can eat +
+
-Animal can sleep +* Animal can eat +* Animal can sleep -Dog can eat +
+
-Dog can sleep +* Dog can eat +* Dog can sleep +* Dog can bark -Dog can bark +
+
-Cat can eat +* Cat can eat +* Cat can sleep +* Cat can meow -Cat can sleep +
+
-Cat can meow +### Inheritance: An example implementation -# Inheritance - Example +
+
+```csharp class Animal - { - -public void Eat() { Console.WriteLine("Eating..."); } - -public void Sleep() { Console.WriteLine("Sleeping..."); } - + public void Eat() + { Console.WriteLine("Eating..."); } + public void Sleep() + { Console.WriteLine("Sleeping..."); } } - class Cat : Animal - { - -public void Meow() { Console.WriteLine("Meow!"); } - + public void Meow() + { Console.WriteLine("Meow!"); } } - class Dog : Animal - -{ - -public void Bark() { Console.WriteLine("Bark!"); } - -} - -class Program - -{ - -static void Main(string[] args) - -{ - -Dog pluto = new Dog(); - -pluto.Eat(); // Outputs "Eating..." - -pluto.Bark(); // Outputs "Bark!" - -} - -} - -# Inheritance - -All the objects deriving from the same base class can be referenced with the base class name: - -Animal whiskersAnimal = new Cat(); - -Animal plutoAnimal = new Dog(); - -However, only the methods of the base class are available for objects of the base class type: - -plutoAnimal.Eat(); // Outputs "Eating..." - -plutoAnimal.Bark(); // Error - -An object of base class type can be __casted __ into the child class type: - -Dog pluto = (Dog)plutoAnimal; - -pluto.Bark(); // Outputs "Bark!" - -# Abstract Classes - -* In some cases you want the base class to be made __abstract__ -* Objects of an abstract class cannot be instantiated - * For example, where would you need a generic Animal by itself? -* Make a class abstract with the abstract keyword: -* abstract class Animal -* { -* public void Eat() { Console.WriteLine("Eating..."); } -* public void Sleep() { Console.WriteLine("Sleeping..."); } -* } -* class Program -* { -* static void Main(string[] args) -* { -* Animal animal = new Animal(); // This will throw an error -* } -* } - -Instead, the methods are accessible through a derived class: - -abstract class Animal - { - -public void Eat() { Console.WriteLine("Eating..."); } - -public void Sleep() { Console.WriteLine("Sleeping..."); } - + public void Bark() + { Console.WriteLine("Bark!"); } } +``` -class Pig : Animal - -{ - -public void Squeal() { Console.WriteLine("Squeee!"); } - -} +
+
+```csharp class Program - { - -static void Main(string[] args) - -{ - -Pig pig = new Pig(); - -pig.Sleep(); // Outputs "Sleeping..." - -pig.Squeal(); // Outputs "Squeee!" - + static void Main(string[] args) + { + Dog pluto = new Dog(); + pluto.Eat(); // Outputs "Eating..." + pluto.Bark(); // Outputs "Bark!" + } } - -} - -If you know you only need the functionality of the abstract class, instantiate the new class as a type of abstract class: - -abstract class Animal{ public void Eat() { Console.WriteLine("Eating..."); } public void Sleep() { Console.WriteLine("Sleeping..."); }}class Pig : Animal{ public void Squeal() { Console.WriteLine("Squeee!"); }}class Program{ static void Main(string[] args) { Animal pig = new Pig(); pig.Sleep(); // Outputs "Sleeping..." pig.Squeal(); // This will throw an error }} +``` + +
+
+ +### Inheritance continued + +* All the objects deriving from the same base class can be referenced with the base class name: + ```csharp + Animal whiskersAnimal = new Cat(); + Animal plutoAnimal = new Dog(); + ``` +* However, only the methods of the base class are available for objects of the base class type: + ```csharp + plutoAnimal.Eat(); // Outputs "Eating..." + plutoAnimal.Bark(); // Error + ``` +* An object of base class type can be *__cast__* into the child class type: + ```csharp + Dog pluto = (Dog)plutoAnimal; + pluto.Bark(); // Outputs "Bark!" + ``` + +## Abstract Classes + +* In some cases you want the base class to be made [abstract](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/abstract) +* Objects of an abstract class ***cannot*** be instantiated + * For example, where would you need a generic `Animal` by itself? +* Make a class abstract with the `abstract` keyword: + ```csharp + abstract class Animal + { + public void Eat() { Console.WriteLine("Eating..."); } + public void Sleep() { Console.WriteLine("Sleeping..."); } + } + class Program + { + static void Main(string[] args) + { + Animal animal = new Animal(); // This will throw an error + } + } + ``` --- -This is called abstraction, which is one of the key concepts of OOP - -# Exercise 1 - -Create the classes Animal, Dog, Cat and Pig. Animal is the same as before (strings name and sound and the Greet() method). Dog, Cat and Pig inherit Animal - -Give Dog, Cat and Pig some fields and/or methods specific to that animal +* Instead, the methods are accessible through a derived class: + ```csharp + abstract class Animal + { + public void Eat() { Console.WriteLine("Eating..."); } + public void Sleep() { Console.WriteLine("Sleeping..."); } + } + class Pig : Animal + { + public void Squeal() { Console.WriteLine("Squeee!"); } + } + class Program + { + static void Main(string[] args) + { + Pig pig = new Pig(); + pig.Sleep(); // Outputs "Sleeping..." + pig.Squeal(); // Outputs "Squeee!" + } + } + ``` -Create a few instances of Dog, Cat and Pig classes, and add them to a new list of Animals, named "allAnimals" - -Loop through allAnimals with the foreach statement, and call the Greet() method of each animal - -# Enum - -__Enum __ (short for enumeration) is a data type for holding a set of constant (immutable) names - -Enums can be useful when you have a number of items or states that are predefined, for example, weekdays - -Create the enum type with the enum keyword: - -enum Weekday{ Monday, Tuesday, Wednesday, Thursday, Friday, Saturday} - -New instances of the enum can only be assigned one of the values within: - -Weekday currentDay = Weekday.Monday; - -# Enum - Example - -In this example, enum is used to keep track of the state of the program: +--- +* If you know you only need the functionality of the abstract class, instantiate the new class as a type of abstract class: + ```csharp + abstract class Animal + { + public void Eat() { Console.WriteLine("Eating..."); } + public void Sleep() { Console.WriteLine("Sleeping..."); } + } + class Pig : Animal + { + public void Squeal() { Console.WriteLine("Squeee!"); } + } + class Program + { + static void Main(string[] args) + { + Animal pig = new Pig(); + pig.Sleep(); // Outputs "Sleeping..." + pig.Squeal(); // This will throw an error + } + } + ``` + +## Exercise 1. Animal farm + + +1) Create the classes `Animal`, `Dog`, `Cat` and `Pig`. `Animal` is the same as before (strings `name` and `sound` and the `Greet()` method). `Dog`, `Cat` and `Pig` inherit `Animal` +2) Give `Dog`, `Cat` and `Pig` some fields and/or methods specific to that animal +3) Create a few instances of `Dog`, `Cat` and `Pig`, and add them to a list `allAnimals` +4) Loop through `allAnimals` with the `foreach` statement, and call the `Greet()` method of each animal + +## Enums + +* [Enum](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/enum) (short for enumeration) is a data type for holding a set of constant (immutable) names +* Enums can be useful when you have a given number of ***states*** that are predefined + * For example, weekdays + * Another example is an extension of boolean with three states `True`, `False` and `Maybe` + +### Creating enums + +* Create an `enum` type with the enum keyword: + ```csharp + enum Season + { + Spring, + Summer, + Autumn, + Winter + } + ``` +* Then, create a new variable with the type `Season` and assign one of the enum type's values to it: + ```csharp + Season currentSeason = Season.Spring; + ``` + +### Enums: An example + +
+
+ +In this example, an enum is used to keep track of the state of the program. + +```csharp enum ProgramState - { - -Login, - -Menu, - -Exit - + Login, + Menu, + Exit } +``` -static void Main(string[] args) - -{ - -ProgramState currentState = ProgramState.Login; - -while (true) - -{ - -switch (currentState) +
+
+```csharp +static void Main(string[] args) { - -case ProgramState.Login: - -// Switch current state to Menu after logging in - -break; - -case ProgramState.Menu: - -// Switch current state to Exit if user exits - -break; - -case ProgramState.Exit: - -// Exit the program with an exit message - -break; - -} - + ProgramState currentState = ProgramState.Login; + while (true) + { + switch (currentState) + { + case ProgramState.Login: + // Switch current state to Menu after logging in + break; + case ProgramState.Menu: + // Switch current state to Exit if user exits + break; + case ProgramState.Exit: + // Exit the program with an exit message + break; + } + } } +``` -} +
+
-# Going Further: Object Oriented Programming +## Extra: Object Oriented Programming + -* The instances that are created with the new -keyword are objects. This is literally what Object Orientation refers to: packing functionality into these reusable variables that are holding some data and can be passed around -* The key concepts of OOP are +* The instances that are created with the `new` keyword are ***objects***. +* This is literally what ***object orientation*** refers to: packing functionality into these reusable variables that are holding some data and can be passed around +* The key concepts of OOP are: * Encapsulation * Inheritance - * Abstraction, and + * Abstraction * Polymorphism -# OOP: Encapsulation - -Earlier we created classes which hold properties and methods, which are only accessible elsewhere _after _ instantiating an object of the class - -All the functionality is encapsulated inside of the class instead of lying around in the codebase - -All the functionality made available _only when it is needed _ by instantiating an object of the class - -# OOP: Inheritance - -As shown in the lecture slides, inheritance allows you to write some functionality once, and then create separate classes which all share that same functionality - -This removes the need to write the same code inside every class - -# OOP: Abstraction +### Encapsulation + -When your class contains a lot of complicated functionality, it doesn't always make sense to reveal everything when the class is used +* Earlier we created classes that hold properties and methods that are only accessible elsewhere ***after*** instantiating an object of the class +* All the functionality is encapsulated inside of the class instead of lying around in the codebase +* All the functionality is made available **_only when it is needed_** by instantiating an object of the class -Instead, reveal only the parts that the user (you, a workmate, etc) actually need, with abstraction +### Inheritance + -Parable: The user of a microwave doesn't have to know about the complicated circuitry inside of the microwave. Only the buttons are revealed +* As shown earlier, inheritance allows you to write some functionality once, and then create separate classes which all share that same functionality +* This removes the need to rewrite the same code inside every class -# OOP: Polymorphism +### Abstraction + -This concept becomes more clear after we have covered interfaces +* When your class contains a lot of complicated functionality, it doesn't always make sense to reveal everything when the class is used +* Instead, reveal only the parts that the user (you, a workmate, etc) actually need, with abstraction +* Example: The user of a microwave doesn't have to know about the complicated circuitry inside of the microwave. Only the buttons are revealed -Polymorphism refers to multiple classes having the same method but with different functionality +### Polymorphism + -This reduces the need for massive if-else and switch..case statements +* This concept becomes more clear after we have covered interfaces in the next lecture +* Polymorphism refers to multiple classes having the same method but with different functionality +* This reduces the need for massive if-else and switch..case statements diff --git a/9-interfaces-slides.html b/9-interfaces-slides.html new file mode 100644 index 0000000..29bb5f8 --- /dev/null +++ b/9-interfaces-slides.html @@ -0,0 +1,306 @@ +9. Interfaces
+

Interfaces

+
+
+

Overview

+
    +
  • Interfaces
  • +
  • Interfaces or Inheritance?
  • +
+
+
+

Interfaces

+
    +
  • In addition to abstract classes, interfaces are a way to achieve abstraction to your program
  • +
  • Interfaces are classes that have no internal functionality
  • +
  • Interfaces describe the methods and properties that a class has to have when implementing the interface +
      +
    • Think of it as a contract: by implementing an interface, the class has to use all the methods and properties defined in the interface
    • +
    +
  • +
  • As with abstract classes, interfaces cannot be instantiated directly +
      +
    • (It wouldn't make any sense as interfaces have no implementation)
    • +
    +
  • +
  • Interfaces are way more commonly used than abstract classes
  • +
+
+
+

Creating an interface

+
    +
  • Define an interface using the interface keyword instead of class:
    interface IUser
    +{
    +  int Id { get; set; }
    +  string Name { get; set; }
    +  void GetUserStatistics();
    +}
    +
    +
  • +
  • Interface names should begin with the capital letter I to more easily identify them as interfaces and not classes
  • +
  • Notice that interfaces can contain both properties and methods but not fields
  • +
  • Methods are declared without the method body (no implementation) +
      +
    • The methods are implemented on the classes that uses the interface
    • +
    +
  • +
+
+
+

Implementing an interface

+
    +
  • Implement an interface just like you would inherit a class:
    class User : IUser
    +{
    +
    +}
    +
    +
  • +
  • The compiler will now throw a bunch of errors saying that the User class does not implement the properties and methods defined in the interface
  • +
  • Let's fix that by defining those next
  • +
+
+
+
class User : IUser
+{
+  public int Id { get; set; }
+  public string Name { get; set; }
+  public void GetUserStatistics()
+  {
+    // Some code here
+  }
+}
+
+
    +
  • The interface is now fully implemented and the compiler is happy
  • +
  • The interface does not dictate how the methods are implemented, those just need to be implemented
  • +
  • Note: To quickly implement the interface, click the IUser interface name and click 💡 > Implement interface.
  • +
+
+
+

Implementing multiple interfaces

+
    +
  • Unlike with inheritance, classes can implement multiple interfaces +
      +
    • In contrast, classes can only inherit from one base class
    • +
    +
  • +
  • This is done by separating the interfaces with a comma:
    class Rock : IPickable, IThrowable, ICrushable
    +{
    +// Code that implements IPickable, IThrowable and ICrushable
    +}
    +
    +
  • +
+
+
+

Why use interfaces?

+
    +
  • Interfaces allow common functionality among classes that are otherwise unrelated to each other
  • +
  • In those cases, inheriting from some shared base class wouldn't make sense
  • +
  • Consider the following example:
    public void DeleteData(IDeletable data)
    +{
    +  data.Delete();
    +}
    +
    +
  • +
  • The above method accepts any type of object that implements IDeletable, regardless of other functionality
  • +
+
+
+

Interface or Inheritance?

+
+
+

Example 1

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
class Dogclass Humanclass Bear
Eat()Eat()Eat()
Sleep()Sleep()Sleep()
WagTail()Contemplate()Hibernate()
+
+
    +
  • All classes could inherit from a base class Animal, which has methods Eat() and Sleep()
  • +
  • The question is, should the base class be abstract? +
      +
    • Depends on your program: do you ever need an object that can only Eat() and Sleep()?
    • +
    +
  • +
+
+
+

Example 2

+
+ + + + + + + + + + + + + + + + + + + + +
class Treeclass Humanclass Car
Grow()Grow()Explode()
Photosynthesize()Move()Move()
+
+
    +
  • It wouldn't make sense to use inheritance here, since there is no functionality that is shared between all classes
  • +
  • Instead you could make two interfaces: IGrowable and IMovable
  • +
+
+
+

Interfaces: An example

+
    +
  • Let's make a program that has two lists: one for all objects that can move (IMovable) and one for all objects that can be carried (ICarryable)
  • +
  • Finally, every movable object is moved and carryable object is carried
  • +
+
+
+
+
+
interface IMovable
+{
+  void Move();
+}
+interface ICarryable
+{
+  void Carry();
+}
+
+
+
+
class Elephant : IMovable
+{
+  public void Move()
+  {
+    Console.WriteLine("The elephant is moving'");
+  }
+}
+class Cat : IMovable, ICarryable
+{
+  public void Move()
+  {
+    Console.WriteLine("The cat is moving'");
+  }
+  public void Carry()
+  {
+    Console.WriteLine("You are carrying the cat");
+  }
+}
+class Rock : ICarryable
+{
+  public void Carry()
+  {
+    Console.WriteLine("You are carrying the rock");
+  }
+}
+
+
+
+
+
+
+
+
class Program
+{
+  static void Main(string[] args)
+  {
+    Elephant elephant = new Elephant();
+    Cat cat = new Cat();
+    Rock rock = new Rock();
+
+    List<IMovable> movables =
+      new List<IMovable>{ elephant, cat };
+    List<ICarryable> carryables =
+      new List<ICarryable>{ cat, rock };
+
+    foreach (IMovable movable in movables)
+      movable.Move();
+
+    foreach (ICarryable carryable in carryables)
+      carryable.Carry();
+  }
+}
+
+
+
+

+
+
+
+
+

Exercise 1: A web of relations

+ +

Create a console application that has an interface IInfo and two classes Product and Category that both implement IInfo.

+
    +
  1. Inside IInfo, declare a property InfoText and a method PrintInfo
  2. +
  3. Implement both the property and method in Product and Category
  4. +
  5. Initialize a couple of products and categories, with info texts of your choice
  6. +
  7. Create a list of type IInfo, and add the products and categories to it
  8. +
  9. Create a main loop, where each time the user presses enter, all the info texts inside the list are printed
  10. +
+
+
+

Exercise 2: The IComparable Interface

+ +

Create a program that sorts a list of shapes by area, using the IComparable interface which is used by the List.Sort() method to know whether the elements should come before or after each other in the list.

+
    +
  1. Start by creating 4 classes: Shape, Square, Triangle, and Circle. Square, Triangle and Circle inherit from Shape, which implements the IComparable<Shape> interface.
  2. +
  3. Shape has a public property double Area. Square, Triangle and Circle have to have constructors to calculate the area: Square and Triangle with length and height, and Circle with radius.
  4. +
+
+
+
    +
  1. The CompareTo(Shape? other) method should return 1 if the area is greater than what is being compared with (Shape other), 0 if the areas are equal, and -1 if the area is smaller.
  2. +
  3. Try out your solution by creating a couple of squares, triangles and circles in a list of shapes, and sorting the list with the .Sort() method.
  4. +
  5. Print the areas in the sorted array with a foreach loop. They should be printed in an increasing order.
  6. +
+
+
\ No newline at end of file diff --git a/9-interfaces.md b/9-interfaces.md index 459f3b7..dfff329 100644 --- a/9-interfaces.md +++ b/9-interfaces.md @@ -1,270 +1,248 @@ -# Interfaces - -![](imgs/9%20Interfaces_0.png) - --- +marp: true +paginate: true +math: mathjax +theme: buutti +title: 9. Interfaces +--- +# Interfaces -# Overview + + -Interfaces +## Overview -Interfaces or Inheritance? +* Interfaces +* Interfaces or Inheritance? -# Interfaces +## Interfaces -* In addition to abstract classes, __interfaces __ are a way to achieve abstraction to your program -* Interfaces are classes that have __no internal functionality__ -* Interfaces describe the methods and properties that a class has to have when implementing the interface - * Think of it as a _contract_ : by __implementing __ an interface, the class _has to_ _use _ all the methods and properties that are defined in the interface -* As with abstract classes, interfaces cannot be instantiated directly - * It wouldn't make any sense as interfaces have no implementation +* In addition to abstract classes, *__interfaces__* are a way to achieve abstraction to your program +* Interfaces are classes that have *__no internal functionality__* +* Interfaces describe the methods and properties that a class has to have when ***implementing*** the interface + * Think of it as a ***contract***: by implementing an interface, the class **_has to use_** all the methods and properties defined in the interface +* As with [abstract classes](8-inheritance-and-abstract-classes.md#abstract-classes), interfaces cannot be instantiated directly + * (It wouldn't make any sense as interfaces have no implementation) * Interfaces are way more commonly used than abstract classes -# Creating an Interface +### Creating an interface * Define an interface using the interface keyword instead of class: -* interface IUser -* { -* int Id { get; set; } -* string Name { get; set; } -* void GetUserStatistics(); -* } -* Interface names should begin with the capital I letter to more easily identify them as interfaces and not classes -* Notice that interfaces can contain both properties and methods but not fields + ```csharp + interface IUser + { + int Id { get; set; } + string Name { get; set; } + void GetUserStatistics(); + } + ``` +* [Interface names should begin](https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces) with the capital letter `I` to more easily identify them as interfaces and not classes +* Notice that interfaces can contain both properties and methods ***but not fields*** * Methods are declared without the method body (no implementation) * The methods are implemented on the classes that uses the interface -# Implementing an Interface - -Implement an interface just like you would inherit a class: - -class User : IUser - -{ - -} +### Implementing an interface -The compiler will now throw a bunch of errors saying that the User class does not implement the properties and methods defined in the interface +* Implement an interface just like you would inherit a class: + ```csharp + class User : IUser + { -Let's fix that by defining those now + } + ``` +* The compiler will now throw a bunch of errors saying that the User class does not implement the properties and methods defined in the interface +* Let's fix that by defining those next -# Implementing an Interface (continued) +--- +```csharp class User : IUser - -{ - -public int Id { get; set; } - -public string Name { get; set; } - -public void GetUserStatistics() - { - -// Some code here - -} - + public int Id { get; set; } + public string Name { get; set; } + public void GetUserStatistics() + { + // Some code here + } } +``` +* The interface is now fully implemented and the compiler is happy +* The interface does not dictate **_how_** the methods are implemented, those just need to be implemented +* ***Note:*** To quickly implement the interface, click the IUser interface name and click _💡 > Implement interface_. -The interface is now fully implemented and the compiler is happy - -The interface do not dictate _how_ the methods are implemented, those just need to be implemented. - -❕ - -To quickly implement the interface, click the IUser interface name and click the light bulb -> implement interface. - -# Implementing Multiple Interfaces +### Implementing multiple interfaces * Unlike with inheritance, classes can implement multiple interfaces * In contrast, classes can only inherit from one base class * This is done by separating the interfaces with a comma: -* class Rock : IPickable, IThrowable, ICrushable -* { -* // Code that implements IPickable, IThrowable and ICrushable -* } - -# Why Use Interfaces? - -Interfaces allow common functionality among classes that are otherwise unrelated to each other + ```csharp + class Rock : IPickable, IThrowable, ICrushable + { + // Code that implements IPickable, IThrowable and ICrushable + } + ``` -In those cases, inheriting from some shared base class wouldn't make sense +### Why use interfaces? -Consider the following example: - -public void DeleteData(IDeletable data) - -{ - -data.Delete(); - -} +* Interfaces allow common functionality among classes that are otherwise unrelated to each other +* In those cases, inheriting from some shared base class wouldn't make sense +* Consider the following example: + ```csharp + public void DeleteData(IDeletable data) + { + data.Delete(); + } + ``` +* The above method accepts **_any_** type of object that implements `IDeletable`, regardless of other functionality -The above method accepts _any _ type of object that implements IDeletable, regardless of other functionality +## Interface or Inheritance? -# Interface or Inheritance? +### Example 1 -| class Dog | -| :-: | -| -Eat()-Sleep()-WagTail() | +
-| class Human | -| :-: | -| -Eat()-Sleep()-Contemplate() | +| `class Dog` | `class Human` | `class Bear` | +|:------------|:----------------|:--------------| +| `Eat()` | `Eat()` | `Eat()` | +| `Sleep()` | `Sleep()` | `Sleep()` | +| `WagTail()` | `Contemplate()` | `Hibernate()` | -| class Bear | -| :-: | -| -Eat()-Sleep()-Hibernate() | +
-All classes could inherit from a base class Animal, which has methods Eat() and Sleep() +* All classes could inherit from a base class `Animal`, which has methods `Eat()` and `Sleep()` +* The question is, should the base class be abstract? + * Depends on your program: do you ever need an object that can ***only*** `Eat()` and `Sleep()`? -Should the base class be abstract? Depends on your program: do you ever need an object that can only Eat() and Sleep()? +### Example 2 -| class Tree | -| :-: | -| -Grow()-Photosynthesize() | +
-| class Human | -| :-: | -| -Grow()-Move() | +| `class Tree` | `class Human` | `class Car` | +|:--------------------|:--------------|:------------| +| `Grow()` | `Grow()` | `Explode()` | +| `Photosynthesize()` | `Move()` | `Move()` | -| class Car | -| :-: | -| -Move()-Explode() | +
-It wouldn't make sense to use inheritance here, since there is no functionality that is shared between all classes +* It wouldn't make sense to use inheritance here, since there is no functionality that is shared between ***all*** classes +* Instead you could make two interfaces: `IGrowable` and `IMovable` -Instead you could make two interfaces: IGrowable and IMovable +## Interfaces: An example -# Interfaces - Example +* Let's make a program that has two lists: one for all objects that can move (`IMovable`) and one for all objects that can be carried (`ICarryable`) +* Finally, every movable object is moved and carryable object is carried -Let's make a program that has two lists: one for all objects that can move (IMovable) and one for all objects that can be carried (ICarryable) +--- -Finally every movable object is moved and carryable object is carried +
+
+```csharp interface IMovable - { - -void Move(); - + void Move(); } - interface ICarryable - { - -void Carry(); - + void Carry(); } +``` -class Elephant : IMovable - -{ - -public void Move() +
+
+```csharp +class Elephant : IMovable { - -Console.WriteLine("The elephant is moving'"); - + public void Move() + { + Console.WriteLine("The elephant is moving'"); + } } - -} - class Cat : IMovable, ICarryable - -{ - -public void Move() - -{ - -Console.WriteLine("The cat is moving'"); - -} - -public void Carry() - { - -Console.WriteLine("You are carrying the cat"); - + public void Move() + { + Console.WriteLine("The cat is moving'"); + } + public void Carry() + { + Console.WriteLine("You are carrying the cat"); + } } - -} - class Rock : ICarryable - { - -public void Carry() - -{ - -Console.WriteLine("You are carrying the rock"); - + public void Carry() + { + Console.WriteLine("You are carrying the rock"); + } } +``` -} - -class Program +
+
-{ +--- -static void Main(string[] args) +
+
+```csharp +class Program { - -Elephant elephant = new Elephant(); - -Cat cat = new Cat(); - -Rock rock = new Rock(); - -List movables = new List{ elephant, cat }; - -List carryables = new List{ cat, rock }; - -foreach (IMovable movable in movables) - -movable.Move(); - -foreach (ICarryable carryable in carryables) - -carryable.Carry(); - + static void Main(string[] args) + { + Elephant elephant = new Elephant(); + Cat cat = new Cat(); + Rock rock = new Rock(); + + List movables = + new List{ elephant, cat }; + List carryables = + new List{ cat, rock }; + + foreach (IMovable movable in movables) + movable.Move(); + + foreach (ICarryable carryable in carryables) + carryable.Carry(); + } } +``` -} +
+
![](imgs/9%20Interfaces_1.png) -# Exercise 1: A Web of Relations - -Create a console application that has an interface IInfo, and two classes Product and Category, which both implement IInfo. +
+
-Inside IInfo, declare a property InfoText and a method PrintInfo -Implement the property and method in Product and Category -Initialize a couple of products and categories, with info texts of your choice +## Exercise 1: A web of relations + -Create a list of type IInfo, and add the products and categories to it +Create a console application that has an interface `IInfo` and two classes `Product` and `Category` that both implement `IInfo`. -Create a main loop, where each time the user presses enter, all the info texts inside the list are printed +1) Inside `IInfo`, declare a property `InfoText` and a method `PrintInfo` +2) Implement both the property and method in `Product` and `Category` +3) Initialize a couple of products and categories, with info texts of your choice +4) Create a list of type `IInfo`, and add the products and categories to it +5) Create a main loop, where each time the user presses enter, all the info texts inside the list are printed -# Exercise 2: The IComparable Interface +## Exercise 2: The `IComparable` Interface + -Create a program that sorts a list of shapes by area, using the [IComparable](https://docs.microsoft.com/en-us/dotnet/api/system.collections.icomparer?view=netcore-3.1) interface, which is used by the List.Sort() method to know whether the elements should come before or after each other in the list. +Create a program that sorts a list of shapes by area, using the [IComparable](https://docs.microsoft.com/en-us/dotnet/api/system.collections.icomparer?view=netcore-3.1) interface which is used by the `List.Sort()` method to know whether the elements should come before or after each other in the list. -Start by creating 4 classes: __Shape__ , __Square__ , __Triangle__ and __Circle__ . Square, Triangle and Circle inherit from Shape. Shape implements the __IComparable\__ __ __ interface. +1) Start by creating 4 classes: `Shape`, `Square`, `Triangle`, and `Circle`. `Square`, `Triangle` and `Circle` inherit from `Shape`, which implements the `IComparable` interface. +2) Shape has a public property `double Area`. `Square`, `Triangle` and `Circle` have to have constructors to calculate the area: `Square` and `Triangle` with `length` and `height`, and `Circle` with `radius`. -Shape has a public property double Area. Square, Triangle and Circle have to have constructors to calculate the area: Square and Triangle with length and height, and Circle with radius. - -The CompareTo(Shape? other) method should return 1 if the area is greater than what is being compared with (Shape other), 0 if the areas are equal, and -1 if the area is smaller. +--- + -Try out your solution by creating a couple of squares, triangles and circles in a list of shapes, and sorting the list with the .Sort() method. Print the areas in the sorted array with a foreach loop. They should be printed in an increasing order. +3) `The CompareTo(Shape? other)` method should return `1` if the area is greater than what is being compared with (`Shape other`), `0` if the areas are equal, and `-1` if the area is smaller. +4) Try out your solution by creating a couple of squares, triangles and circles in a list of shapes, and sorting the list with the `.Sort()` method. +5) Print the areas in the sorted array with a `foreach` loop. They should be printed in an increasing order. diff --git a/README.md b/README.md index c032995..9c27c21 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,9 @@ Material completion denoted with 🌑🌘🌗🌖🌕 . | # | Lecture | Materials | Exercises | |---:|------------------------------------------------------------------------|----------:|----------:| +| 8 | [Inheritance and Abstract Classes](8-inheritance-and-abstract-classes.md) | 🌕 | 🌕 | +| 9 | [Interfaces](9-interfaces.md) | 🌕 | 🌕 | +| 10 | [Static Members, Methods, and Classes](10-static-members-methods-and-classes.md) | 🌕 | 🌕 | | 11 | [Delegates and Events](11-delegates-and-events.md) | 🌕 | 🌗 | | 12 | [Files and Streams](12-files-and-streams.md) | 🌕 | 🌕 | | 13 | [Generics, IEnumberable and LINQ](13-generics-ienumerable-and-linq.md) | 🌕 | 🌕 |