scenarios: 06 buzzkill, 07 wip
This commit is contained in:
parent
ee2e91c954
commit
e11e594be0
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,259 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="210mm"
|
||||||
|
height="297mm"
|
||||||
|
viewBox="0 0 210 297"
|
||||||
|
version="1.1"
|
||||||
|
id="svg5"
|
||||||
|
inkscape:version="1.2.1 (9c6d41e4, 2022-07-14)"
|
||||||
|
sodipodi:docname="jd-02-derived-interfaces.svg"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview7"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:zoom="2.4712112"
|
||||||
|
inkscape:cx="230.4538"
|
||||||
|
inkscape:cy="357.31467"
|
||||||
|
inkscape:window-width="1534"
|
||||||
|
inkscape:window-height="894"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="25"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
inkscape:current-layer="layer1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid1775" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="bspline"
|
||||||
|
id="path-effect4248"
|
||||||
|
is_visible="true"
|
||||||
|
lpeversion="1"
|
||||||
|
weight="33.333333"
|
||||||
|
steps="2"
|
||||||
|
helper_size="0"
|
||||||
|
apply_no_weight="true"
|
||||||
|
apply_with_weight="true"
|
||||||
|
only_selected="false" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
inkscape:label="Слой 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:4.9389px;font-family:'PT Astra Serif';-inkscape-font-specification:'PT Astra Serif';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="38.364582"
|
||||||
|
y="80.697914"
|
||||||
|
id="text2244"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
id="tspan2246"
|
||||||
|
x="38.364582"
|
||||||
|
y="80.697914" /></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Mono';-inkscape-font-specification:'IBM Plex Mono';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="52.916668"
|
||||||
|
y="71.4375"
|
||||||
|
id="text2252"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan2250"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'IBM Plex Mono';-inkscape-font-specification:'IBM Plex Mono';stroke-width:0.265"
|
||||||
|
x="52.916668"
|
||||||
|
y="71.4375">Animal</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Mono';-inkscape-font-specification:'IBM Plex Mono';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="54.239582"
|
||||||
|
y="85.989586"
|
||||||
|
id="text2306"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan2304"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="54.239582"
|
||||||
|
y="85.989586">Human</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Mono';-inkscape-font-specification:'IBM Plex Mono';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="82.020836"
|
||||||
|
y="85.989586"
|
||||||
|
id="text2310"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan2308"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="82.020836"
|
||||||
|
y="85.989586">Bull</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Mono';-inkscape-font-specification:'IBM Plex Mono';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="76.729164"
|
||||||
|
y="116.41667"
|
||||||
|
id="text2314"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan2312"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="76.729164"
|
||||||
|
y="116.41667">Minotaurus</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Mono';-inkscape-font-specification:'IBM Plex Mono';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="29.104166"
|
||||||
|
y="85.989586"
|
||||||
|
id="text3268"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3266"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="29.104166"
|
||||||
|
y="85.989586">Wolf</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Mono';-inkscape-font-specification:'IBM Plex Mono';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="36.380207"
|
||||||
|
y="103.18753"
|
||||||
|
id="text3272"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3270"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="36.380207"
|
||||||
|
y="103.18753">Werewolf</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Mono';-inkscape-font-specification:'IBM Plex Mono';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="9.260417"
|
||||||
|
y="103.1875"
|
||||||
|
id="text4002"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan4000"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="9.260417"
|
||||||
|
y="103.1875">Jackal</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Mono';-inkscape-font-specification:'IBM Plex Mono';fill:#000000;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="38.364582"
|
||||||
|
y="124.35419"
|
||||||
|
id="text4006"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan4004"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="38.364582"
|
||||||
|
y="124.35419">Anubis</tspan></text>
|
||||||
|
<rect
|
||||||
|
style="fill:none;stroke-width:0.264999;stroke-linecap:square;stroke:#000000;stroke-opacity:1"
|
||||||
|
id="rect4114"
|
||||||
|
width="23.8125"
|
||||||
|
height="7.9375"
|
||||||
|
x="50.270832"
|
||||||
|
y="66.145836" />
|
||||||
|
<rect
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
id="rect4116"
|
||||||
|
width="18.520834"
|
||||||
|
height="7.9375"
|
||||||
|
x="26.458332"
|
||||||
|
y="80.697914" />
|
||||||
|
<rect
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
id="rect4118"
|
||||||
|
width="21.166666"
|
||||||
|
height="7.9375"
|
||||||
|
x="51.59375"
|
||||||
|
y="80.697914" />
|
||||||
|
<rect
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
id="rect4120"
|
||||||
|
width="18.520834"
|
||||||
|
height="7.9375"
|
||||||
|
x="79.375"
|
||||||
|
y="80.697914" />
|
||||||
|
<rect
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
id="rect4122"
|
||||||
|
width="23.8125"
|
||||||
|
height="7.9375"
|
||||||
|
x="6.614583"
|
||||||
|
y="97.895836" />
|
||||||
|
<rect
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
id="rect4124"
|
||||||
|
width="37.041668"
|
||||||
|
height="7.9375"
|
||||||
|
x="74.083328"
|
||||||
|
y="111.125" />
|
||||||
|
<rect
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
id="rect4126"
|
||||||
|
width="23.8125"
|
||||||
|
height="7.9375"
|
||||||
|
x="35.71875"
|
||||||
|
y="119.0625" />
|
||||||
|
<rect
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
id="rect4128"
|
||||||
|
width="30.427082"
|
||||||
|
height="7.9375"
|
||||||
|
x="33.734375"
|
||||||
|
y="97.895836" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
d="M 55.562499,74.083332 37.041666,80.697916"
|
||||||
|
id="path4130" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
d="m 62.177083,74.083332 v 6.614584"
|
||||||
|
id="path4132" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
d="m 68.791666,74.083332 19.84375,6.614584"
|
||||||
|
id="path4134" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
d="M 68.791667,88.635417 84.666664,111.125"
|
||||||
|
id="path4136"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
d="M 89.958333,88.635417 96.572911,111.125"
|
||||||
|
id="path4138"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
d="M 30.427083,88.635416 17.197916,97.895832"
|
||||||
|
id="path4140" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
d="M 15.875,105.83333 42.333333,119.0625"
|
||||||
|
id="path4142"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
d="m 56.885416,88.635416 -9.260417,9.260416"
|
||||||
|
id="path4240" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
d="m 37.041666,88.635416 5.291667,9.260416"
|
||||||
|
id="path4244" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
d="m 63.499999,88.635416 c 3.527956,6.173923 7.055733,12.347534 5.071244,17.418574 -1.98449,5.07104 -9.480867,9.03971 -16.977494,13.00851"
|
||||||
|
id="path4246"
|
||||||
|
inkscape:path-effect="#path-effect4248"
|
||||||
|
inkscape:original-d="m 63.499999,88.635416 c 3.528042,6.173874 7.055821,12.347484 10.583333,18.520834 -7.496413,3.96909 -14.992791,7.93776 -22.489583,11.90625" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 10 KiB |
|
@ -0,0 +1,325 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="210mm"
|
||||||
|
height="297mm"
|
||||||
|
viewBox="0 0 210 297"
|
||||||
|
version="1.1"
|
||||||
|
id="svg5"
|
||||||
|
inkscape:version="1.2.1 (9c6d41e4, 2022-07-14)"
|
||||||
|
sodipodi:docname="jd-02-interfaces-use.svg"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview7"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:zoom="1.0579349"
|
||||||
|
inkscape:cx="290.6606"
|
||||||
|
inkscape:cy="384.71176"
|
||||||
|
inkscape:window-width="1534"
|
||||||
|
inkscape:window-height="876"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="25"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
inkscape:current-layer="layer1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid1049" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<g
|
||||||
|
inkscape:label="Слой 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
|
||||||
|
x="31.75"
|
||||||
|
y="71.4375"
|
||||||
|
id="text1468"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1466"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.265;-inkscape-font-specification:'IBM Plex Sans';font-family:'IBM Plex Sans';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
|
||||||
|
x="31.75"
|
||||||
|
y="71.4375" /></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="23.8125"
|
||||||
|
y="66.145836"
|
||||||
|
id="text1724"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1722"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="23.8125"
|
||||||
|
y="66.145836">Привет, мир</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="71.4375"
|
||||||
|
y="68.791664"
|
||||||
|
id="text1728"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1726"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="71.4375"
|
||||||
|
y="68.791664">Котики</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="66.145836"
|
||||||
|
y="79.375"
|
||||||
|
id="text1782"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1780"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="66.145836"
|
||||||
|
y="79.375">Собачки</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="29.104166"
|
||||||
|
y="58.208332"
|
||||||
|
id="text1786"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1784"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="29.104166"
|
||||||
|
y="58.208332">Методы</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="68.791664"
|
||||||
|
y="50.270832"
|
||||||
|
id="text1790"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1788"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="68.791664"
|
||||||
|
y="50.270832">Классы</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="100.54166"
|
||||||
|
y="42.333332"
|
||||||
|
id="text1794"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1792"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="100.54166"
|
||||||
|
y="42.333332">Пакеты</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="97.895836"
|
||||||
|
y="71.4375"
|
||||||
|
id="text1798"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1796"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="97.895836"
|
||||||
|
y="71.4375">java.io</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="95.25"
|
||||||
|
y="84.666664"
|
||||||
|
id="text1802"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1800"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="95.25"
|
||||||
|
y="84.666664">java.nio</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="71.4375"
|
||||||
|
y="92.604164"
|
||||||
|
id="text1806"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1804"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="71.4375"
|
||||||
|
y="92.604164">java.utils</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="55.5625"
|
||||||
|
y="-132.29167"
|
||||||
|
id="text1810"
|
||||||
|
transform="rotate(90)"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1808"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="55.5625"
|
||||||
|
y="-132.29167">Внешние файлы</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="35.71875"
|
||||||
|
y="101.86459"
|
||||||
|
id="text1814"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1812"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="35.71875"
|
||||||
|
y="101.86459">read</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="51.59375"
|
||||||
|
y="112.44791"
|
||||||
|
id="text1818"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1816"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="51.59375"
|
||||||
|
y="112.44791">write</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="66.145836"
|
||||||
|
y="105.83334"
|
||||||
|
id="text1822"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1820"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="66.145836"
|
||||||
|
y="105.83334">concatenate</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="103.1875"
|
||||||
|
y="113.77084"
|
||||||
|
id="text1826"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1824"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="103.1875"
|
||||||
|
y="113.77084">search</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="111.125"
|
||||||
|
y="100.54166"
|
||||||
|
id="text1830"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1828"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="111.125"
|
||||||
|
y="100.54166">copy</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="15.875"
|
||||||
|
y="128.32292"
|
||||||
|
id="text1834"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1832"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="15.875"
|
||||||
|
y="128.32292">Интерфейсы</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="10.583333"
|
||||||
|
y="115.09375"
|
||||||
|
id="text1834-1"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1832-4"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="10.583333"
|
||||||
|
y="115.09375">Интерфейсы</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="13.229167"
|
||||||
|
y="93.927086"
|
||||||
|
id="text1834-6"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1832-3"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="13.229167"
|
||||||
|
y="93.927086">Интерфейсы</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="15.875"
|
||||||
|
y="83.34375"
|
||||||
|
id="text1834-2"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1832-6"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="15.875"
|
||||||
|
y="83.34375">Интерфейсы</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="21.166666"
|
||||||
|
y="140.22917"
|
||||||
|
id="text1838"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1836"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="21.166666"
|
||||||
|
y="140.22917">Другие программы</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.9389px;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-linecap:square"
|
||||||
|
x="18.520834"
|
||||||
|
y="71.4375"
|
||||||
|
id="text1842"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1840"
|
||||||
|
style="stroke-width:0.265"
|
||||||
|
x="18.520834"
|
||||||
|
y="71.4375">Поиск в массиве</tspan></text>
|
||||||
|
<rect
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
id="rect2054"
|
||||||
|
width="47.625"
|
||||||
|
height="15.875"
|
||||||
|
x="15.875"
|
||||||
|
y="60.854164" />
|
||||||
|
<rect
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
id="rect2056"
|
||||||
|
width="79.375"
|
||||||
|
height="39.6875"
|
||||||
|
x="13.229166"
|
||||||
|
y="44.979168" />
|
||||||
|
<rect
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
id="rect2058"
|
||||||
|
width="113.77083"
|
||||||
|
height="58.208332"
|
||||||
|
x="10.583333"
|
||||||
|
y="37.041668" />
|
||||||
|
<rect
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
id="rect2060"
|
||||||
|
width="132.29167"
|
||||||
|
height="82.020836"
|
||||||
|
x="7.9375"
|
||||||
|
y="34.395832" />
|
||||||
|
<rect
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264999;stroke-linecap:square;stroke-opacity:1"
|
||||||
|
id="rect2062"
|
||||||
|
width="60.854168"
|
||||||
|
height="18.520823"
|
||||||
|
x="13.229167"
|
||||||
|
y="129.64583" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 14 KiB |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 9.6 KiB |
|
@ -201,9 +201,9 @@
|
||||||
|
|
||||||
06-29 & На этой лекции мы познакомились с тем, как создавать окна, поговорили о менеджерах размещений, элементах графического интерфейса, и обработчиках событий. Многое осталось за границей этой лекции, во многом из-за того, что мы ещё не изучили такие интересные темы, как многопоточность и программные интерфейсы, но обязательно изучим. Изучение графических фреймворков не должно становиться для вас целью, если не хотите связать своё будущее с фронтенд разработкой, а раз уж вы здесь, думаю, вы уже сделали свой выбор. Разработка графического интерфейса подобного рода должна стать утилитарной задачей, то есть, решаться по мере поступления каких-то вопросов, поэтому мы оставим вопрос разработки графических интерфейсов на будущее самостоятельное изучение или даже лучше - просто периодически будем к ним возвращаться и делать наши приложения более привлекательными визуально. \\ \hline
|
06-29 & На этой лекции мы познакомились с тем, как создавать окна, поговорили о менеджерах размещений, элементах графического интерфейса, и обработчиках событий. Многое осталось за границей этой лекции, во многом из-за того, что мы ещё не изучили такие интересные темы, как многопоточность и программные интерфейсы, но обязательно изучим. Изучение графических фреймворков не должно становиться для вас целью, если не хотите связать своё будущее с фронтенд разработкой, а раз уж вы здесь, думаю, вы уже сделали свой выбор. Разработка графического интерфейса подобного рода должна стать утилитарной задачей, то есть, решаться по мере поступления каких-то вопросов, поэтому мы оставим вопрос разработки графических интерфейсов на будущее самостоятельное изучение или даже лучше - просто периодически будем к ним возвращаться и делать наши приложения более привлекательными визуально. \\ \hline
|
||||||
|
|
||||||
06-29 & В качестве домашнего задания именно по графическим интерфейсам нужно будет полностью и досконально разобраться с кодом. Не бойтесь записывать свои вопросы и задавать их на семинарах и наставникам. А чтобы попрактиковаться в программировании нужно переделать метод проверки победы, чтобы на него не было больно смотреть. Будет классно, если получится сделать метод проверки победы для поля любого размера и любого числа крестиков-ноликов для победы, то есть, например, чтобы победить на поле 5х5 нужно собрать линию из 4х крестиков. Ну и если останется время, я отметил это задание аж двумя звёздочками, подумайте, как сделать компьютер немного умнее, чем просто случайным. специально отмечу в формулировке задания слово примитивно, потому что никто не ожидает от вас каких-то разборов графовых алгоритмов, минимакса и прочей теории игр. \\ \hline
|
06-30 & В качестве домашнего задания именно по графическим интерфейсам нужно будет полностью и досконально разобраться с кодом. Не бойтесь записывать свои вопросы и задавать их на семинарах и наставникам. А чтобы попрактиковаться в программировании нужно переделать метод проверки победы, чтобы на него не было больно смотреть. Будет классно, если получится сделать метод проверки победы для поля любого размера и любого числа крестиков-ноликов для победы, то есть, например, чтобы победить на поле 5х5 нужно собрать линию из 4х крестиков. Ну и если останется время, я отметил это задание аж двумя звёздочками, подумайте, как сделать компьютер немного умнее, чем просто случайным. специально отмечу в формулировке задания слово примитивно, потому что никто не ожидает от вас каких-то разборов графовых алгоритмов, минимакса и прочей теории игр. \\ \hline
|
||||||
|
|
||||||
06-30 & На сегодня это всё. Напоследок соглашусь с Иоганном Вольфгангом фон Гёте, если не очень нравится что-то делать, научиться этому будет довольно трудно. а если трудно, то правильно ли выбрано направление? Любите то, чему учитесь, знания будут сами собой оставаться в голове, без усилий. \\ \hline
|
06-31 & На сегодня это всё. Напоследок соглашусь с Иоганном Вольфгангом фон Гёте, если не очень нравится что-то делать, научиться этому будет довольно трудно. а если трудно, то правильно ли выбрано направление? Любите то, чему учитесь, знания будут сами собой оставаться в голове, без усилий. \\ \hline
|
||||||
\end{longtable}
|
\end{longtable}
|
||||||
|
|
||||||
\end{document}
|
\end{document}
|
||||||
|
|
|
@ -11,64 +11,109 @@
|
||||||
|
|
||||||
Отбивка & и сегодня на повестке дня у нас интерфейсы, но не те интерфейсы, что графические, а те, что программные. \\ \hline
|
Отбивка & и сегодня на повестке дня у нас интерфейсы, но не те интерфейсы, что графические, а те, что программные. \\ \hline
|
||||||
|
|
||||||
На прошлом уроке & На прошлом уроке мы поговорили о файловых системах и представлении данных в запоминающих устройствах; Поверхностно посмотрели на популярные пакеты ввода-вывода. Подробно разобрали один из самых популярных ссылочных типов данных String и разные механики вокруг него, такие как стрингбилдер и стрингпул. \\ \hline
|
На прошлом уроке & На прошлом уроке мы поговорили как раз о графических интерфейсах пользователя. создали немного окон, разместили немного компонентов, порисовали. Поговорили о графических интерфейсах через призму создания и взаимодействия объектов, нарисовали пару-тройку диаграмм, чтобы лучше запомнить, что как и с чем связывается, кто кого вызывает и зачем. \\ \hline
|
||||||
|
|
||||||
На этом уроке & Поговорим об интерфейсах, рассмотрим понятие и принцип работы, поговорим о ключевом слове implements; Наследование и множественное наследование интерфейсов, реализация, значения по умолчанию и частичная реализация интерфейсов. Естественно, что говоря об интерфейсах нельзя не сказать о функциональных интерфейсах и анонимных классах. Коротко рассмотрим модификаторы доступа при использовании интерфейсов и немного подробнее поговорим о глубинных процессах, таких как раннее и позднее связывание в объектно-ориентированном программировании. \\ \hline
|
На этом уроке & Поговорим об интерфейсах, рассмотрим понятие и принцип работы, поговорим о ключевом слове implements; Наследование и множественное наследование интерфейсов, реализация, значения по умолчанию и частичная реализация интерфейсов. Естественно, что говоря об интерфейсах нельзя не сказать о функциональных интерфейсах и анонимных классах. Коротко рассмотрим модификаторы доступа при использовании интерфейсов и немного подробнее поговорим о глубинных процессах, таких как раннее и позднее связывание в объектно-ориентированном программировании. \\ \hline
|
||||||
|
|
||||||
06-01 & Разговор об интерфейсах хотелось бы построить не так, как мы это делали на лекциях обычно, а от некоторой практической составляющей, чтобы где-то в середине лекции у вас сложилось явное впечатление, что что-то тут явно можно улучшить, а когда мы применим интерфейсы, вы подумали «ааааа так вот зачем оно нужно и как применяется», а потом уже поговорим о теоретической составляющей и особенностях. \\ \hline
|
06-01 & Разговор об интерфейсах хотелось бы построить не так, как мы это делали на лекциях обычно, а от некоторой практической составляющей, чтобы где-то в середине лекции у вас сложилось явное впечатление, что что-то тут явно можно улучшить, а когда мы применим интерфейсы, вы подумали «ааааа так вот зачем оно нужно и как применяется», а потом уже поговорим о теоретической составляющей и особенностях. \\ \hline
|
||||||
|
|
||||||
Отбивка & Приложение для примера \\ \hline
|
|
||||||
|
|
||||||
06-02 & Итак начнём с преамбулы, здесь я призываю вас не особенно обращать внимание на то, какие именно классы и методы используются, а внимательно следить за взаимодействием и отношениями объектов, потому что интерфейсы, о которых мы сегодня планируем поговорить - это как раз механизм упрощающий и универсализирующий взаимодействия объектов. Код может показаться непростым, но зато задачу мы поставим таким образом, что если делать нормально, то без интерфейсов не обойтись, и когда мы закончим - у вас, как я только что и сказал, должно появиться ощущение что «о, так вот зачем они нужны». Почему будет сложно? потому что несмотря на то что вы уже знаете принципы ооп - надо уметь их применять.\\ \hline
|
06-02 & Итак начнём с преамбулы, здесь я призываю вас не особенно обращать внимание на то, какие именно классы и методы используются, а внимательно следить за взаимодействием и отношениями объектов, потому что интерфейсы, о которых мы сегодня планируем поговорить - это как раз механизм упрощающий и универсализирующий взаимодействия объектов. Код может показаться непростым, но зато задачу мы поставим таким образом, что если делать нормально, то без интерфейсов не обойтись, и когда мы закончим - у вас, как я только что и сказал, должно появиться ощущение что «о, так вот зачем они нужны». Почему будет сложно? потому что несмотря на то что вы уже знаете принципы ооп - надо уметь их применять.\\ \hline
|
||||||
|
|
||||||
06-03 & Итак, что мы будем делать? мы сделаем некий небольшой набросок своего собственного игрового 2д движка, без физики и прочего, а просто с объектами и анимацией, чисто демонстрационный. на его основе можно что угодно запилить, и будет отлично работать. На слайде вы видите окно, кружки летают (имейте ввиду, они перемещаются плавно, если у кого-то что-то дёргается, это интернет с низким ФПС передаёт, а не приложение). пока что ничего тут не обрабатывается, ничего толком не происходит. Итак, самое главное, что нам понадобится, это окно, которое будет как-то взаимодействовать с операционной системой, на окне будет канва, на которой мы будем всё рисовать, и собственно объекты, которые мы будем рисовать. \\ \hline
|
06-03 & Итак, что мы будем делать? мы сделаем некий небольшой набросок своего собственного игрового 2д движка, без физики и прочего, а просто с объектами и анимацией, чисто демонстрационный. На его основе можно что угодно запилить, и будет отлично работать. На слайде вы видите окно, кружки летают (имейте ввиду, они перемещаются плавно, если у кого-то что-то дёргается, это интернет с низким ФПС передаёт, а не приложение). пока что ничего тут не обрабатывается, ничего толком не происходит. Итак, самое главное, что нам понадобится, это окно, которое будет как-то взаимодействовать с операционной системой, на окне будет канва, на которой мы будем всё рисовать, и собственно объекты, которые мы будем рисовать. \\ \hline
|
||||||
|
|
||||||
06-04 & Быстро создаём окно, буквально константы с размерами, координатами, и конструктор окна прямо здесь же вместе с методом мейн, не вдаваясь в подробности того, как работает фреймворк свинг на котором мы всё это пишем, на эту тему у нас будет отдельный урок, на котором мы закрепим информацию об ООП, многопоточности и отлову исключений в графических интерфейсах. Самое важное для нас сейчас - это то, что окно - это объект с какими-то свойствами и каким-то поведением. Если коротко, стартуем программу, создаём объект окна, говорим, что окно с каким-то заголовком, какого-то размера и находится по каким-то координатам, а когда мы нажмём на крестик, то закрыть нужно будет не только окно, но и программу целиком. \\ \hline
|
06-04 & Быстро создаём окно, буквально константы с размерами, координатами, и конструктор окна прямо здесь же вместе с методом мейн, не вдаваясь в подробности того, как работает фреймворк свинг на котором мы всё это пишем, на эту тему у нас был отдельный урок, на котором уже закрепили информацию об ООП. Самое важное для нас сейчас - это то, что окно - это объект с какими-то свойствами и каким-то поведением. Если коротко, стартуем программу, создаём объект окна, говорим, что окно с каким-то заголовком, какого-то размера и находится по каким-то координатам, а когда мы нажмём на крестик, то закрыть нужно будет не только окно, но и программу целиком. \\ \hline
|
||||||
|
|
||||||
06-05 & Итак есть такой компонент JPanel, с ним можно много что делать но самое интересное, что можно на нём рисовать. Итак создали наследника Jpanel с названием GameCanvas. Что умеет любой компонент в свинге? он умеет перерисовываться, посредством вызова метода paintComponent. Применим полиморфизм. Из документации мы знаем, что метод пэинтКомпонент вызывается тогда, когда фреймворку надо перерисовать панельку. Мы этот метод переопределим и напишем свою собственную реализацию перерисовки. Давайте сделаем так: создадим конструктор этой пенльки, и будем в конструкторе делать что то незначительное, например, менять цвет фона на синий. Заоверрайдили пэинтКомпонент и тут-же вызвали родительский метод. То есть по сути мы говорим, что нас вполне устраивает то, как перерисовывается панелька, но мы потом захотим туда что-то добавить. Ну и добавим четыре метода, возвращающие границы нашей канвы, левую, правую, верхнюю, нижнюю.\\ \hline
|
06-05 & Припоминаем, что есть такой компонент JPanel, с ним можно много что делать но самое интересное, что можно на нём рисовать. Итак создали наследника Jpanel с названием MainCanvas. Что умеет любой компонент в свинге? правильно, он умеет перерисовываться, посредством вызова метода paintComponent. Применяем полиморфизм. Из документации мы знаем, что метод пэинтКомпонент вызывается тогда, когда фреймворку надо перерисовать панельку. Мы этот метод переопределим и напишем свою собственную реализацию перерисовки. Давайте сделаем так: создадим конструктор панельки, и будем в конструкторе делать что то незначительное, например, менять цвет фона на синий. Заоверрайдили пэинтКомпонент и тут-же вызвали родительский метод. То есть по сути мы говорим, что нас вполне устраивает то, как перерисовывается панелька, но мы потом захотим туда что-то добавить. Ну и добавим четыре метода, возвращающие границы нашей канвы, левую, правую, верхнюю, нижнюю, для удобства дальнейшего взаимодействия с получившейся канвой.\\ \hline
|
||||||
|
|
||||||
06-06 & Наладим взаимодействие компонентов и привяжем все действия нашего игрушечного движка ко времени физического мира. В нашем основном окошке, в конструкторе, создали переменную класса GameCanvas и расположили её на окне прям в центре. Пока что всё понятно и хорошо. Всё работает. В принципе можно начать писать логику игры прям здесь, в классе панельки, но это архитектурно не очень хорошо, ведь это же канва на которой мы рисуем, значит здесь мы должны по логике только рисованием заниматься. Давайте примем архитектурное решение писать логику игры в нашем классе с кружками, а GameCanvas будет универсальным, чтобы рисовать вообще всё что угодно. Для этого описали в нашем основном окошке метод, назвали его как-нибудь нормально onDrawFrame и в нём будем описывать реализацию цикла для нашего модного приложения, то есть так называемую бизнес-логику. На данный момент это будут два метода - апдейт который будет как то изменять состояние нашего приложения, и рендер, который будет отдавать команды всяким рисующим компонентам. \\ \hline
|
06-06 & Наладим взаимодействие компонентов и привяжем все действия нашего игрушечного движка ко времени физического мира. В основном окошке, в конструкторе, создали переменную класса MainCanvas и расположили её на окне прям в центре, пусть на окне будет только она. Пока что всё понятно и хорошо. Всё работает. В принципе можно начать писать логику игры прям здесь, в классе канвы, но это архитектурно не очень хорошо, ведь это же канва на которой мы рисуем, значит здесь мы должны по логике только рисованием заниматься. Давайте примем архитектурное решение писать логику игры в нашем классе с кружками, а MainCanvas будет универсальным, чтобы иметь возможность в дальнейшем рисовать вообще всё что угодно. Для этого описали в нашем основном окошке метод, назвали его как-нибудь нормально onDrawFrame и в нём будем описывать реализацию цикла для нашего модного приложения, то есть так называемую бизнес-логику. На данный момент это будут два метода - апдейт который будет как то изменять состояние нашего приложения, и рендер, который будет отдавать команды всяким рисующим компонентам. То есть получается, что канва время от времени будет говорить, что она нарисовалась, а основное окно по этому событию будет что-то умное предпринимать \\ \hline
|
||||||
|
|
||||||
06-07 & Теперь нам надо чтобы при перерисовке наш с вами GameCanvas этот метод дёргал, и тем самым изображение как-то менялось. Для этого нашей канве надо знать как минимум чей метод она будет дёргать, то есть ей нужно знать на каком окне она находится. создаём в классе канвы локальную переменную, которая умеет хранить объекты класса MainCircles и передадим значение этой переменной в конструкторе. И в пэинтКомпоненте будем вызывать controller.onDrawFrame(); Далее, чтобы зациклить это действие мы можем пойти несколькими путями: самый простой - создать постоянно обновляющуюся канву, то есть в методе пэинтКомпонент взять и написать repaint() но это вариант прямо скажем "так себе", он полностью нагрузит одно из ядер процессора только отрисовкой окна - не самое лучшее применение одного из ядер. Второй путь - это применение магии из занятия по потокам. мы можем заставить наш поток какое-то время поспать, начиная с 20-й строки вы видите некоторую конструкцию, смысл которой вам будет понятен немного позже Thread.sleep(16); это даст нам фпс близкий к 60, приемлемо для условной игры, не надо ни больше ни меньше, пожалуй. Получится, что мы отрисовали компонент, посчитали что там изменится апдейтом, отправили обратно на отрисовку рендером, отрисовали пэинтКомпонентом.\\ \hline
|
06-07 & Теперь надо чтобы при перерисовке наш с вами MainCanvas этот метод дёргал, и тем самым изображение как-то менялось. Для этого канве надо знать как минимум чей метод она будет дёргать, то есть ей нужно знать на каком окне она находится. создаём в классе канвы локальную переменную, которая умеет хранить объекты класса MainWindow и передадим значение этой переменной в конструкторе. А в пэинтКомпоненте будем вызывать нужный метод controller.onDrawFrame();
|
||||||
|
%% 2
|
||||||
|
|
||||||
06-08 & Довольно интересно, кстати, как при этом изменился код, вызывающий конструктор канвы, ведь мы из основного класса с окном теперь как-то должны в канву передать это самое основное окно, как вы могли догадаться, для этой цели мы применяем указатель на текущий объект класса this, то есть в конструкторе основного окна мы передали ссылку на экземпляр этого окна канве. немного ломает привычное использование для обращения к полям в конструкторе, но, поверьте, то ли ещё будет. Предлагаю запомнить такой способ применения ключевого слова this, он нам сегодня ещё пригодится. \\ \hline
|
Далее, чтобы зациклить это действие мы можем пойти несколькими путями: самый простой - создать постоянно обновляющуюся канву, то есть в методе пэинтКомпонент взять и написать repaint() но это вариант прямо скажем "так себе", он полностью нагрузит одно из ядер процессора только отрисовкой окна - не самое лучшее применение одного из ядер.
|
||||||
|
%% 3
|
||||||
|
|
||||||
06-09 & Закончим с отрисовкой и методом onDrawFrame. Он будет обновлять сцену и рендерить её. Для обновления сцены было бы очень неплохо знать дельту времени, которая прошла с предыдущего кадра, чтобы обновлять физику. Конечно можно писать физику, опираясь на частоту кадра, или на то что мы там спим 16миллисекунд, но это всё очень сомнительная опора, потому что мы гарантированно спим 16миллисекунд, но сколько именно мы будем спать неизвестно, потому что отрисовка происходит не через фиксированные промежутки времени и ещё куча факторов. Лучше всего точно знать сколько времени прошло с предыдущего кадра. поэтому сделаем так чтобы метод onDrawFrame эту самую дельту у канвы получал и отдавал методу обновления. Соответственно считаем дельту в канве. Вот, собственно и вся физика, которая нам понадобится. Теперь посмотрим вот на что - у нас в пэинтКомпонент прилетает объект класса графикс, который отвечает, как это ни удивительно, за графику, то есть за рисование. Это же то, что нам нужно. Давайте этот самый объект отдадим нашему методу onDrawFrame, пусть он что-нибудь рисует. а где рисует? на канве, значит нам надо будет как минимум знать её размеры. какой канвы размеры получаем? нашей, той самой. себя и отдадим. onDrawFrame будет распределять - апдейту отдаст дельту и канву, а рендеру - канву и графику. Для универсальности. Все изменения канвы вы видите на слайде, все изменения основного окна ему соответствуют, изменена сигнатура метода онДроФрейм, на неё мы посмотрим через несколько секунд. Пока самое главное, что нам нужно понять об этих двух объектах - канва считает для нас время и постоянно перерисовывает себя, сообщая об этом факте основному окну, а основное окно на этот факт как-то реагирует. Ну и ООП вокруг этого тоже было бы хорошо понимать, объекты передают ссылки друг на друга и вызывают друг у друга всякие интересные методы. \\ \hline
|
Второй путь - это применение магии из занятия по потокам. мы можем заставить наш поток какое-то время поспать, поэтому мы вызываем статический метод класса Трэд, он называется слип и принимает на вход количество миллисекунд, которое поток должен обязательно поспать. это даст нам фпс близкий к 60, приемлемо для условной игры, не надо ни больше ни меньше, пожалуй.
|
||||||
|
%% 4
|
||||||
|
|
||||||
06-10 & Давайте попробуем что нибудь нарисовать при помощи нашего с вами игрового цикла, например прямую белую линию. Видим, что отлично получается, теперь мы умеем рисовать и наша канва умеет это отображать. Отлично. Наше приложение будет рисовать какие-то объекты, будут это кружки, квадратики, картинки, человечки или какие-то другие объекты - не важно. Важно, чтобы у программы было описан механизм и поведение этих объектов. Это как раз то, о чём я говорил и говорю - применение архитектуры, применение ООП. Мало просто посмотреть уроки, почитать книжки, посидеть на семинаре. Надо сидеть и думать в рамках парадигмы ООП. Это ещё простенькая архитектура. Я понимаю вас, вы смотрите сейчас, и вроде всё понятно, а сами в жизни бы такое не написали. Я сам несколько лет назад такое в жизни не написал бы, так что не переживайте, всё придёт с опытом. Главное, не путайте понятия уметь программировать и знать язык программирования. В какой-то момент вы поймаете себя на мысли, что вы не думаете о циклах и условиях, а думаете на следующем уровне абстракции, думаете о взаимосвязях, об архитектуре, а пальцы сами набирают какие-то языковые конструкции. \\ \hline
|
Получится, что мы создали внутри этого метода некий бесконечный цикл отрисовки, своеобразный ду-вайл, который сам себя заставляет крутиться дальше с некоторой периодичностью и на каждой своей итерации сообщает контроллеру, что прошло около одной шестидесятой секунды. \\ \hline
|
||||||
|
|
||||||
06-11 & Соответственно, рисовать просто линии круги и прочее - довольно скучно, поэтому будем рисовать объекты, Создадим класс Спрайт. Ни от чего наследоваться не будем. Просто опишем общее для всех рисуемых объектов в нашей программе поведение. Что может быть у всех объектов в приложении общего? размеры, местоположение. Обычно, когда вы начинаете изучать какой-то графический фреймворк вы замечаете, что начало координат у этого фреймворка находится в верхнем левом или нижнем левом углу. Однако очень часто, когда пишутся какие-то игры или другие приложения с использованием графики в качестве координат используется центр объекта. То есть надо условиться - что х и у - это центр любого визуального объекта на нашей канве. И соответственно удобно хранить не длину-ширину, а половину длины и половину ширины. А границы объекта соответственно будем отдавать через геттеры и сеттеры. Дополнительно научим наш спрайт рисоваться. Ну как научим, просто скажем, что он умеет обновляться и рендериться, а его наследники пусть уже решают, как именно они хотят это делать. Но спрайты лишены логики, они ничего не знают о том, как именно будут меняться их свойства. \\ \hline
|
06-08 & Довольно интересно, кстати, как при этом изменился код, вызывающий конструктор канвы, ведь мы из основного класса с окном теперь как-то должны в канву передать это самое основное окно, как вы могли догадаться, для этой цели мы применяем указатель на текущий объект класса this, то есть в конструкторе основного окна мы передали ссылку на экземпляр этого окна канве. немного ломает привычное использование для обращения к полям в конструкторе, но, поверьте, то ли ещё будет. Предлагаю запомнить такой способ применения ключевого слова this, он нам сегодня ещё пригодится. Ещё раз: создавая экземпляр основного окна мы передаём ссылку на этот создаваемый экземпляр канве, чтобы она знала, у какого окна дёргать метод обновления. \\ \hline
|
||||||
|
|
||||||
06-12 & Поэтому естественно нужно создать класс собственно шарика, который будет по нашему экрану прыгать, а то непорядок какой-то. В конструкторе задаём ему рэндомные размеры. Давайте придумаем ему какие-нибудь глобальные свойства. Можно конечно придумать класс, который будет направлять наш спрайт и вообще задавать ему скорость и прочие физические величины, но мы ж с вами пример пишем, так что придумаем ему просто - скорость по осям х и у соответственно и цвет. для цвета есть совершенно неожиданно называющийся класс Color которому можно задать величины в формате РГБ в диапазоне от 0 до 255. Для шарика переопределяем апдейт и рендер. суперы нам не нужны, они всё равно пустые. Самый простой рендер - мы объекту графики зададим цвет текущего шарика и сделаем fillOval, которому передадим лево, верх, ширину и высоту. Несмотря на то что наши объекты содержат поля типа флоут, мы работаем с пиксельной системой координат (что конечно же не подходит для реальных проектов, там нужно всё сразу переводить в мировые координаты (например принять центр экрана за 0, верх и лево за -1 низ и право за 1, как это делает OpenGL) чтобы рендерить экраны). Но это нам и пяти лекций не хватит чтобы вникнуть так что не будем. А в методе апдейт мы просто прибавляем к нашим текущим координатам нашу скорость, умноженную на дельту времени, то есть как в третьем классе. Расстояние, которое должен был преодолеть наш шарик за то время пока наш поток спал и наша канва рендерилась. ну и обрабатываем отскоки, то есть описываем 4 условия, что при достижении границы мы меняем направление вектора. \\ \hline
|
06-09 & Закончим с отрисовкой и методом onDrawFrame. Он будет обновлять сцену и рендерить её. Для обновления сцены было бы очень неплохо знать дельту времени, которая прошла с предыдущего кадра, чтобы обновлять мир. Конечно можно писать, опираясь на частоту кадра, или на то что мы там спим 16миллисекунд, но это очень сомнительная опора, потому что мы гарантированно спим 16миллисекунд, но сколько именно мы будем выполнять остальные действия - неизвестно, потому что отрисовка происходит не через фиксированные промежутки времени а по очереди сообщений окна и ещё куча факторов, поэтому, лучше всего точно знать сколько времени прошло с предыдущего кадра. Сделаем так чтобы метод onDrawFrame эту самую дельту у канвы получал и отдавал методу обновления. Возможно, метод ещё захочет знать, какая именно канва отрисовалась, вдруг их будет несколько, да и вдруг нам для логики понадобится узнавать размеры канвы... и нам нужен будет объект графики с канвы, чтобы отдавать ей команды на рисование.
|
||||||
|
%% 2
|
||||||
|
|
||||||
06-13 & давайте быстренько допилим основной класс и будем переходить к беседе об интерфейсах уже, а то чувствую вы подустали от вступлений. В основном классе мы делаем очень прямолинейно - создаём классовый массив из спрайтов и называться он будет sprites и мы говорим что будет у нас допустим 1 кружчек. В методе апдейт мы пробежимся по всем спрайтам и скажем каждому из них - апдейться так как ты умеешь. В методе рендер мы сделаем тоже самое - пробежимся по всем спрайтам и скажем - отрисуйся так, как ты хочешь. И всё, реализацию обновления и отрисовки мы оставили самим объектам, то есть инкапсулировали в них, только каждый объект сам по себе знает, как именно ему обновляться с течением времени, и как рисоваться, а основной экран уже управляет - на какой канве, когда и кого рисовать. Итак инициализировали наше приложение одним новым шариком и напишем небольшую магию по добавлению новых шариков в динамически расширяемый массив. Как известно, в джава все массивы имеют неизменяемую размерность. Это накладывает некоторые архитектурные ограничения на программиста, но мы ж с вами крутые программисты, вон сколько лекций и семинаров позади, можем обмануть систему. Код не сложный, когда старый массив заполнился, просто увеличиваем его в два раза и переносим шарики из старого в новый. \\ \hline
|
Соответственно считаем дельту в канве. Важно, чтобы привести всё к привычному времени, например, пиксель-в-секунду, отдавать время в секундах, поэтому дополнительно переводим из наносекунд в секунды. Вот, собственно и вся физика, которая нам понадобится. отдадим себя и отдадим свой объект графики, чтобы основная логика могла узнать наши размеры и на нас же рисовать. Все изменения канвы вы видите на слайде, все изменения основного окна ему соответствуют. Пока самое главное, что нам нужно понять об этих двух объектах - канва считает для нас время в физическом мире и постоянно перерисовывает себя, сообщая об этом факте основному окну, а основное окно на этот факт как-то реагирует. Ну и ООП вокруг этого тоже было бы хорошо понимать, объекты передают ссылки друг на друга и вызывают друг у друга всякие интересные методы. \\ \hline
|
||||||
|
|
||||||
06-14 & И осталось эти методы откуда-то вызывать. Мы на нашу канву в конструкторе вешаем слушателя мышки, который нам рассказывает когда произоши какие-то события. Сегодня как раз будем анонимные классы проходить, поговорим об этом явлении подробнее. И по этому произошедшему событию мы говорим - добавь нам спрайт с новым мячиком, у которого будут координаты этого события. Для этого конечно пришлось немного модифицировать класс шарика, добавив в него ещё один конструктор, который сразу задаёт начальные координаты. На правую кнопку мышки повесим удаление спрайта из списков обновления и отрисовки. \\ \hline
|
06-10 & Рисовать несложные штуки мы научились буквально на прошлой лекции. Наше приложение будет рисовать какие-то объекты, будут это кружки, квадратики, картинки, человечки или какие-то другие объекты - не важно. Важно, чтобы у программы было описан механизм и поведение этих объектов. Это как раз то, о чём я говорил и говорю - применение архитектуры, применение ООП. Мало просто посмотреть уроки, почитать книжки, посидеть на семинаре. Надо сидеть и думать в рамках парадигмы ООП. Это ещё простенькая архитектура. Я догадываюсь, что вы смотрите сейчас, и вроде всё понятно, а сами в жизни бы такое не написали. Я сам несколько лет назад такое в жизни не написал бы, так что не переживайте, всё придёт с опытом. Главное, не путайте понятия уметь программировать и знать язык программирования. В какой-то момент вы поймаете себя на мысли, что вы не думаете о циклах и условиях, а думаете на следующем уровне абстракции, думаете о взаимосвязях, об архитектуре, а пальцы сами набирают какие-то языковые конструкции. \\ \hline
|
||||||
|
|
||||||
06-15 & Получается, мы меньше чем за полчаса написали довольно простое и очень хорошо расширяемое приложение, которое не только рисует вещи, но и на действия пользователя реагирует, кажется, неплохо. Напомню, что самое главное, что мы должны из этого приложения извлечь - это взаимодействия и взаимовлияния объектов. Наследование, полиморфизм, инкапсуляция поведений и свойств. Если честно, я слегка устал от синего цвета нашего фона и решил создать отдельный класс фона, но сразу столкнулся с необходимостью думать головой. Логично было бы предположить, что фон - это спрайт, имеющий прямоугольную форму и всегда рисующийся первым. но вот беда, при изменении размеров окна фон тоже желательно изменить в размерах. Поэтому в отрисовке я просто говорю канве, что она должна изменить свой цвет фона, а что, ссылка то на канву у меня есть. Цвет фона я меняю синусоидально по каждому из трёх компонент цвета, поэтому изменение происходит довольно плавно. В общем, получается, что от спрайта нам фактически нужно только поведение, а свойства не нужны. Но и отказаться от наследования нам бы не хотелось, потому что тогда мы не сможем фон единообразно в составе массива спрайтов обновлять. Это наталкивает нас на мысль об унификации поведения, на мысль об интерфейсе. \\ \hline
|
06-11 & Соответственно, рисовать просто линии круги и прочее - довольно скучно, поэтому будем рисовать объекты, Создадим класс Спрайт. Ни от чего наследоваться не будем. Просто опишем общее для всех рисуемых объектов в нашей программе поведение. Что может быть у всех объектов в приложении общего? размеры, местоположение. Обычно, когда вы начинаете изучать какой-то графический фреймворк вы замечаете, что начало координат у этого фреймворка находится в верхнем левом или нижнем левом углу. Однако очень часто, когда пишутся какие-то игры или другие приложения с использованием графики в качестве координат используется центр объекта. То есть надо условиться - что икс и игрек - это центр любого визуального объекта на нашей канве. И соответственно удобно хранить не длину-ширину, а половину длины и половину ширины. А границы объекта соответственно будем отдавать через геттеры и сеттеры. Дополнительно научим наш спрайт рисоваться. Ну как научим, просто скажем, что он умеет обновляться и рендериться, а его наследники пусть уже решают, как именно они хотят это делать. Но спрайты лишены логики, они ничего не знают о том, как именно будут меняться их свойства. \\ \hline
|
||||||
|
|
||||||
Отбивка Понятие интерфейса & Механизм наследования очень удобен, но он имеет свои ограничения. В частности мы можем наследовать только от одного класса, в отличие, например, от языка С++, где имеется множественное наследование \\ \hline
|
06-12 & Поэтому естественно нужно создать класс собственно шарика, который будет по нашему экрану прыгать, а то непорядок какой-то. В конструкторе задаём мячику рэндомные размеры. Давайте придумаем ему какие-нибудь глобальные свойства. Можно конечно придумать класс, который будет направлять наш спрайт и вообще задавать ему скорость и прочие физические величины, но мы ж с вами пример пишем, так что придумаем ему просто - скорость по осям х и у соответственно и цвет.
|
||||||
|
%% 2
|
||||||
|
|
||||||
интерфейс - это описание способов взаимодействия с объектом. фото руля-педалей-коробки, фото юсб, фото клавиатуры-мышки-монитора & В языке Java эту проблему частично позволяют решить интерфейсы. Интерфейсы определяют некоторый функционал, не имеющий конкретной реализации, который затем реализуют классы, применяющие эти интерфейсы. И один класс может применить к себе множество интерфейсов. Правильно говорить реализовать интерфейс, будем сразу говорить правильно. Если сказать проще, интерфейс можно очень-очень грубо представить как очень-очень абстрактный класс. До седьмой джавы это был просто набор методов без реализации. Начиная с восьмой наделали много тонкостей, с ними и будем разбираться. Итак интерфейс - это описание методов. Примером интерфейса в реальной жизни может быть интерфейс управления автомобилем, интерфейс взаимодействия с компьютером или даже интерфейс USB, так, компьютеру не важно, что именно находится по ту сторону провода, флешка, веб-камера или мобильный телефон, а важно, что компьютер умеет работать с интерфейсом USB, отправлять туда байты или получать. Потоки ввода-вывода, которые мы проходили чуть раньше - это тоже своего рода интерфейс, соединяющий не важно какой программный код и не важно какой, например, файл. Все методы во всех интерфейсах всегда публичные, и в классическом варианте не имеют реализации. Ну и поскольку все методы всегда паблик то этот модификатор принято просто не писать. Для новичка это неочевидно и сбивает с толку, может показаться что модификатор дефолтный, а на самом деле он публичный, поблагодарим разработчиков джавы и пойдём дальше. \\ \hline
|
Для шарика переопределяем апдейт и рендер. суперы здесь не нужны, они всё равно пустые. Самый простой рендер - мы объекту графики зададим цвет текущего шарика и сделаем fillOval, которому передадим лево, верх, ширину и высоту. Несмотря на то что наши объекты содержат поля типа флоут, мы работаем с пиксельной системой координат, а значит надо переводить в целые числа, (что конечно же не подходит для реальных проектов, там нужно всё сразу переводить в мировые координаты (например принять центр экрана за 0, верх и лево за -1 низ и право за 1, как это делает OpenGL) чтобы рендерить экраны). Но это нам и пяти лекций не хватит чтобы вникнуть так что не будем.
|
||||||
|
%% 3
|
||||||
|
|
||||||
06-16 & Интерфейсы объявляются также, как классы, и вообще могут иметь очень похожую на класс структуру, то есть быть вложенным или внутренним, но чаще всего интерфейсы описывают в отдельном файле, также как класс, но используя ключевое слово интерфейс. Создадим пару интерфейсов, например, человек и бык, опишем в них методы, например, ходить и издавать звуки. \\ \hline
|
А в методе апдейт мы просто прибавляем к текущим координатам шарика его скорость, умноженную на дельту времени, то есть как в третьем классе. Расстояние, которое должен был преодолеть шарик за то время пока канва спала и рендерилась. ну и обрабатываем отскоки, то есть описываем 4 условия, что при достижении границы мы меняем направление вектора. \\ \hline
|
||||||
|
|
||||||
06-17 & Для чего мы так сделали? Продолжим пример, создадим пару классов, класс мужчина и класс был. Класс мужчины будет у нас реализовывать интерфейс человека. То есть множественного наследования нет, но мы можем реализовать сколько угодно интерфейсов. Для того, чтобы реализовать интерфейс - мы должны переопределить все его методы, либо сделать класс абстрактным. Вот, статический анализатор кода в идее нам об этом явно говорит. Выведем модное сообщение о том что это классы мужчины или быка.
|
06-13 & быстренько допилим основной класс и будем переходить к беседе об интерфейсах уже, а то чувствую вы под-устали от вступлений. В основном классе мы делаем очень прямолинейно - создаём массив из спрайтов и называться он будет sprites и мы говорим что будет у нас допустим 10 кружчков. В методе апдейт мы пробежимся по всем спрайтам и скажем каждому из них - апдейться так как ты умеешь. В методе рендер мы сделаем тоже самое - пробежимся по всем спрайтам и скажем - отрисуйся так, как ты хочешь. И всё, реализацию обновления и отрисовки мы оставили самим объектам, то есть инкапсулировали в них, только каждый объект сам по себе знает, как именно ему обновляться с течением времени, и как рисоваться, а основной экран уже управляет - на какой канве, когда и кого рисовать. В конструкторе же добавим простой цикл инициализирующий приложение десятью шариками. \\ \hline
|
||||||
И теперь самая соль - мы можем в мэйне объявлять не только классы и создавать объекты, но и создать переменную, которая реализовывает интерфейс. То есть тут могут лежать абсолютно никак не связанные между собой объекты, главное, чтобы они реализовывали интерфейсА. И мы можем работать с методами интерфейса, которые могут быть для разных классов вообще по-разному реализованы. Такой вот полиморфизм. Понимаете насколько сильно это отличается от наследования, когда мы с вами создавали общий абстрактный класс животное и от него наследовали наших котиков? \\ \hline
|
|
||||||
|
|
||||||
06-18 & Чтобы стало сильно понятнее, создадим класс минотавра, кто плохо помнит греческую мифологию, это такой товарищ, который с телом человека и головой быка скучно сидел в лабиринте и ждал заблудившихся путников. соответственно, реализовывал интерфейсы человека и быка своим способом, ходил на ногах человека, но не мычал, как бык, а загадки загадывал. Интересно то, что в программе мы можем к минотавру обратиться не только как к человеку, но и как к быку, то есть гипотетически, можно создать некоторого Тесея, погонщика минотавровых стад. Но это уже, так сказать, полёт фантазии, нас интересует только техническая часть вопроса - классы не связаны между собой наследованием, а обращение к ним единообразное. \\ \hline
|
06-14 & Получается, мы меньше чем за час, с учётом того что этот код надо как-то набрать, написали довольно простое и очень хорошо расширяемое приложение, которое рисует штуки. Напомню, что самое главное, что мы должны из этого приложения извлечь - это взаимодействия и взаимовлияния объектов. Наследование, полиморфизм, инкапсуляция поведений и свойств. Если честно, я слегка устал от синего цвета фона, а внимательный зритель мог заметить, что в одном из последних снимков с кодом я убрал строку, изменяющую цвет фона из конструктора. Начать разговор об интерфейсах я решил с создания отдельного класса фона, но сразу столкнулся с необходимостью думать головой. \\ \hline
|
||||||
|
|
||||||
06-19 & Также важно, что в интерфейсах разрешено наследование. То есть у нас интерфейс может наследоваться от другого интерфейса, соответственно при реализации интерфейса мы должны переопределить методы всех родителей нашего интерфейса, то есть тут картина очень похожа на наследование классов, но внимание не запутайтесь, в интерфейсах разрешено множественное наследование. \\ \hline
|
06-15 & Логично было бы предположить, что фон - это спрайт, имеющий прямоугольную форму и всегда рисующийся первым. Но, вот беда, при изменении размеров окна фон тоже желательно изменить в размерах, а это лишние слушатели и десятки строк кода, поэтому в отрисовке класса Фон я просто говорю канве, что она должна изменить свой цвет фона. А что, ссылка то на канву у меня есть, имею право. Цвет фона я меняю синусоидально по каждому из трёх компонент цвета, поэтому изменение происходит плавно. В общем, получается, что от спрайта, фактически, нужно только поведение, а свойства не нужны. Но и отказаться от наследования нам бы не хотелось, потому что тогда мы не сможем фон единообразно в составе массива спрайтов обновлять. Это наталкивает нас на мысль об унификации поведения, на мысль об интерфейсе. \\ \hline
|
||||||
|
|
||||||
06-20 & На несколько минут вернёмся к бэкграунду, пока мы его не забыли, применим наши новые интерфейсные знания на практике. Фон наследуется от спрайта, но ему от спрайта вообще ничего не надо, кроме двух методов. в которых он полностью пишет собственную реализацию, которая никак не коррелирует с тем, как ведут себя остальные спрайты. И вот сложилась ситуация в которой нам надо хранить в одном массиве очень похожие объекты но наследовать их друг от друга не логично. Как поправить? \\ \hline
|
06-16 & Механизм наследования очень удобен, но он имеет свои ограничения. В частности мы можем наследовать только от одного класса, в отличие, например, от языка С++, где имеется множественное наследование \\ \hline
|
||||||
|
|
||||||
06-21 & Напишем некий интерфейс, назовём его GameObject и скажем, что у него есть методы апдейт и рендер, без реализации. То есть это будут некие объекты которые должны уметь рисоваться и обновляться. Идём в спрайт, и говорим, что мы реализуем интерфейс гейм объекта. Смотрим, что сломалось, кто навскидку скажет, почему? Не нужно судорожно хвататься за клавиатуру, но мысль правильная - модификатор должен быть паблик. И Фон тоже теперь у нас реализует интерфейс гейм объекта. При этом получается, то фон вообще никак не связан со спрайтом, у них даже набор полей разный. Но оба умеют рисоваться и апдейтиться, благодаря интерфейсу. Быстро поправив основное окно и логику, сменив массив спрайтов на массив геймОбъектов запускаем и видим как бодро летают наши шарики. \\ \hline
|
06-17 & В языке Java эту проблему частично позволяют решить интерфейсы. Интерфейсы определяют некоторый функционал, не имеющий конкретной реализации, который затем реализуют классы, применяющие эти интерфейсы. И один класс может применить к себе множество интерфейсов. Правильно говорить реализовать интерфейс, будем сразу говорить правильно. Если сказать проще, интерфейс можно очень-очень грубо представить как очень-очень абстрактный класс. До седьмой джавы это был просто набор методов без реализации. Начиная с восьмой наделали много тонкостей, с ними и будем разбираться. Итак интерфейс - это описание методов. Примером интерфейса в реальной жизни может быть интерфейс управления автомобилем, интерфейс взаимодействия с компьютером или даже интерфейс USB, так, компьютеру не важно, что именно находится по ту сторону провода, флешка, веб-камера или мобильный телефон, а важно, что компьютер умеет работать с интерфейсом USB, отправлять туда байты или получать. Потоки ввода-вывода, которые мы проходили чуть раньше - это тоже своего рода интерфейс, соединяющий не важно какой программный код и не важно какой, например, файл. \\ \hline
|
||||||
|
|
||||||
06-22 & И вот мы подошли к самому главному, той гибкости, которую даёт нам работа с интерфейсами. Если вы обратите внимание, как развивается наше повествование по курсу, вы заметите, что сначала мы выходили за пределы одного метода, потом за пределы одного класса, затем за пределы одного пакета, за пределы программного кода, а теперь вовсе хотим написать код, который возможно будет использовать несколькими программами. Посмотрим со стороны, что мы тут понаписали. У наших классов канвы и спрайта, а также у интерфейса нет никакой специфики, их можно применить где угодно. Универсальные получились штуковины. Создадим какую-то условную вторую игру: новый пакет, новый класс, скопипастим немного кода, чтобы всё запускалось. И не писать же нам по новой спрайты и интерфейсы. сделаем правильное дробление по пакетам. то есть получается, что у нас есть некий библиотечный пакет, и какие-то игры с конкретными реализациями. создадим пакет КОММОН и переносим туда канву, спрайт и геймобъект, и ща будем всё чинить. Структура же понятна, только что её всесторонне обговорили? \\ \hline
|
06-18 & Интерфейсы объявляются также, как классы, и вообще могут иметь очень похожую на класс структуру, то есть быть вложенным или внутренним, но чаще всего каждый отдельный интерфейс описывают в отдельном файле, также как класс, но используя ключевое слово интерфейс. Создадим пару интерфейсов, например, человек и бык, опишем в них методы, например, ходить и издавать звуки. Все методы во всех интерфейсах всегда публичные, и в классическом варианте не имеют реализации. Ну и поскольку все методы всегда паблик то этот модификатор принято просто не писать. Для новичка это неочевидно и сбивает с толку, может показаться что модификатор дефолтный, а на самом деле он публичный, видите, среда разработки отметила ключевое слово паблик как лишнее? поблагодарим разработчиков джавы и пойдём дальше. \\ \hline
|
||||||
|
|
||||||
06-23 & Гейм объект это интерфейс, ему вообще на всё плевать, только импорты лишние выкинем. Спрайт тоже не сломался, модификаторы доступа поправим на публичные и защищённые, где это возможно. Второе главное окно также инитим конструктор, размеры, положение. И вот хотим воспользоваться нашей канвой. Но не даёт же. почему, мы ж так классно всё придумали, никакой специфики. Но нет, канва то может принимать в конструкторе mainCircles. и канва уже у этого класса вызывает метод onDrawFrame(). Как это решается? это решается интерфейсом. нам надо написать какой-то интерфейс вроде canvasPaintListener, который будет уметь ждать от канвы вызов метода и как-то по своему его реализовывать. А то у нас получается катастрофа - игры зависят от общего пакета, а по хорошему общий пакет вообще ничего не должен знать о том, какие игры он помогает создать. Создаём в общем пакете интерфейс с одним методом, который имеет сигнатуру из нашего mainCircles. И перепишем канву, чтобы она не какой-то класс с шариками на вход принимала, а canvasPaintListener, назовём переменную листнер. и везде используем слушателя через интерфейс. В главном окне мы говорим что классы вы конечно хорошие, с прекрасным наследованием от фреймворка, но только ещё будете реализовывать интерфейс слушателя канвы. а метод у нас уже правильно написан, с верной сигнатурой. Чтобы подчеркнуть, что это реализация интерфейса, напишем аннотацию оверрайд. \\ \hline
|
06-19 & Для чего мы так сделали? Продолжим пример, создадим пару классов, класс мужчина и класс бык. Класс мужчины будет реализовывать интерфейс человека, а класс быка внезапно быка. Для того, чтобы реализовать интерфейс - мы должны переопределить все его методы, либо сделать класс абстрактным. Статический анализатор кода в идее нам об этом явно скажет. Выведем модное сообщение о том что это методы мужчины или быка. То есть множественного наследования нет, но мы можем реализовать сколько угодно интерфейсов.
|
||||||
|
%% 2
|
||||||
|
|
||||||
06-24 & Насладимся летающими шариками в одном приложении, и летающими квадратиками в другом. Теперь на основе нашего очень хорошо отделённого интерфейсами общего пакета можно штамповать такие приложения практически без усилий. Понимаете, как разработчики в игровых студиях делают по сотне очень похожих игр в год? \\ \hline
|
И теперь получается самая соль - мы можем в объявлять не только классы и создавать объекты, но и создать переменную, которая реализовывает интерфейс. То есть тут могут лежать абсолютно никак не связанные между собой объекты, главное, чтобы они реализовывали интерфейс. И мы можем работать с методами интерфейса, которые могут быть для разных классов вообще по-разному реализованы. Такой вот полиморфизм. Понимаете насколько сильно это отличается от наследования, когда мы с вами создавали общий абстрактный класс животное и от него наследовали наших котиков? \\ \hline
|
||||||
|
|
||||||
|
06-20 & Чтобы стало сильно понятнее, создадим класс минотавра. Для тех, кто не застал античную грецию, напоминаю это такой товарищ, который с телом человека и головой быка скучно сидел в лабиринте и ждал заблудившихся путников. Соответственно, реализовывал интерфейсы человека и быка каким-то своим способом, а именно, ходил на ногах человека, но не мычал, как бык, а загадки загадывал. Интересно то, что в программе мы можем к минотавру обратиться не только как к человеку, но и как к быку, то есть гипотетически, можно создать некоторого Тесея, погонщика минотавровых стад. Но это уже, так сказать, полёт фантазии, нас интересует только техническая часть вопроса - классы не связаны между собой наследованием, а обращение к ним единообразное. \\ \hline
|
||||||
|
|
||||||
|
06-21 & Также важно, что в интерфейсах разрешено наследование. То есть у нас интерфейс может наследоваться от другого интерфейса, соответственно при реализации такого, наследующего интерфейса, мы должны переопределять не только методы интерфейса, но и методы всех его родителей, то есть тут картина очень похожа на наследование классов, но внимание не запутайтесь, в интерфейсах разрешено множественное наследование. То есть ваш милый домашний пушистый котик может быть также одновременно сумасшедшим ночным тыгыдыком и хищником-убийцей из дикой природы. Ну или вот, как на слайде, много разной мифологии. Это у меня сюда ещё химера не поместилась. \\ \hline
|
||||||
|
|
||||||
|
06-22 & Давно я не задавал никаких вопросов, уже устали, наверное. Давайте отвлечёмся и ответим на пару вопросов. 1. Программный интерфейс - это: 1. окно приложения в ОС; 2. реализация методов объекта; 3. объявление методов, реализуемых в классах.
|
||||||
|
|
||||||
|
... 30сек ...
|
||||||
|
это объявление методов, которые потом будут реализованы каждым классом по-своему. Далее... Интерфейсы нужны для: 1. компенсации отсутствия множественного наследования; 2. отделения API и реализации; 3. оба варианта верны.
|
||||||
|
|
||||||
|
... 30 сек...
|
||||||
|
оба варианта верны, интерфейсы это достаточно гибкий инструмент, который выступает в роли безопасной замены множественного наследования и позволяет отделить АПИ от реализации. И последнее в этом подразделе. Интерфейсы позволяют: 1. удобно создавать новые объекты, не связанные наследованием; 2. единообразно обращаться к методам объектов, не связанных наследованием; 3. полностью заменить наследование.
|
||||||
|
|
||||||
|
... 30 сек ...
|
||||||
|
Конечно, полностью заменить наследование не получится, и ни о каком удобстве создания объектов речи не идёт, интерфейсы действительно позволяют единообразно обращаться к объектам, не связанным наследованием, но реализующим один интерфейс. как флешки-мышки и прочая ЮЗБи периферия, помните? \\ \hline
|
||||||
|
|
||||||
|
06-23 & На несколько минут вернёмся к фону, пока мы его полностью не забыли, применим наши новые интерфейсные знания на практике. Фон наследуется от спрайта, но ему от спрайта вообще ничего не нужно, кроме двух методов, в которых он реализует своё собственное поведение, которое в свою очередь никак не коррелирует с тем, как ведут и что хранят в себе остальные спрайты. И вот сложилась ситуация в которой нам надо хранить в одном массиве спрайтов в основной программе очень похожие объекты но наследовать их друг от друга не совсем логично. Как поправить? \\ \hline
|
||||||
|
|
||||||
|
06-24 & Напишем некий интерфейс, назовём его Interactable и скажем, что у него есть методы апдейт и рендер, без реализации. Вообще, если по хорошему, нужно было создавать два интерфейса, Updatable и Renderable, Чтобы иметь возможность отделить рисуемые объекты от обновляемых, но у нас же с вами пример, поэтому мы создадим единый интерфейс. То есть это будут некие объекты которые должны уметь рисоваться и обновляться. Идём в спрайт, и говорим, что мы реализуем интерфейс взаимодействуемого. Смотрим, что сломалось, кто навскидку скажет, почему? Не нужно судорожно хвататься за клавиатуру, но мысль правильная - модификатор должен быть паблик, потому что интерфейс по умолчанию содержит публичные методы, а сужать область видимости запрещено.
|
||||||
|
%% 2
|
||||||
|
|
||||||
|
И Фон тоже теперь у нас реализует интерфейс Interactable. При этом получается, то фон вообще никак не связан со спрайтом, у них даже набор полей разный. Но при этом, оба умеют рисоваться и апдейтиться, благодаря интерфейсу. Быстро поправив основное окно и логику, сменив массив спрайтов на массив интерактивностей можем запустить и увидеть, как снова весьма бодро по экрану летают наши шарики. \\ \hline
|
||||||
|
|
||||||
|
06-25 & И вот мы подошли к самому главному, той гибкости, которую даёт нам работа с интерфейсами. Если вы обратите внимание, как развивается наше повествование по курсу, вы заметите, что сначала мы выходили за пределы одного метода, потом за пределы одного класса, затем за пределы одного пакета, за пределы программного кода, а теперь вовсе хотим написать код, который возможно будет использовать несколькими программами.
|
||||||
|
%% 2
|
||||||
|
|
||||||
|
Посмотрим со стороны, что мы тут написали. У классов канвы и спрайта, а также у интерфейса нет никакой специфики, их можно применять, по сути, где угодно, не только в этой конкретной программе с этими конкретными классами. Универсальные получились штуковины. Создадим какую-то условную вторую игру: новый пакет, новый класс, скопипастим туда немного кода от мячиков. И не писать же нам по новой спрайты и интерфейсы. сделаем правильное дробление по пакетам и станет очевидно, что у нас есть некий общий библиотечный пакет, и какие-то игры с конкретными реализациями. создадим пакет common, переносим туда канву, спрайт и геймобъект, и будем всё чинить. \\ \hline
|
||||||
|
|
||||||
|
06-26 & Те кто делает это прямо сейчас, смотря эту лекцию в записи, могут обратить внимание, что общий пакет перенёсся вовсе без проблем, шарики перенеслись с минимальными изменениями, только публичные модификаторы понадобились. Во втором главном окне создали такой же конструктор, размеры, положение. И вот хотим воспользоваться общей канвой. Но не даёт же. Почему? мы же так классно всё придумали, никакой специфики. Но нет, канва то может принимать в конструкторе только мэйн окна из пакета кружочков. и канва уже у этого класса вызывает метод onDrawFrame(). Привязались к классу, связали себя по рукам и ногам сразу.
|
||||||
|
%% 2
|
||||||
|
|
||||||
|
Как это решается? это решается интерфейсом. нам надо написать какой-то интерфейс вроде canvasRepaintListener, который будет уметь ждать от канвы вызов метода и как-то по своему его реализовывать. А то у нас получается катастрофа - игры зависят от общего пакета, а по хорошему общий пакет вообще ничего не должен знать о том, какие игры он помогает создать. Создаём в общем пакете интерфейс с одним методом, который имеет сигнатуру из mainWindow. И переписываем канву так, чтобы она не какой-то класс с шариками на вход принимала, а canvasRepaintListener. и везде используем слушателя через интерфейс.
|
||||||
|
%% 3
|
||||||
|
|
||||||
|
Внимательно смотрите на ещё один фокус. Мы помним, что интерфейс может быть реализован классом, а наши окна - это тоже классы. И вот они наследуются от ДжейФрейма. Привычные нам наследование и полиморфизм утверждают, что это всё, что мы можем сделать. А мы нашим классам внезапно говорим что классы вы конечно хорошие, с прекрасным наследованием от фреймворка, но теперь ещё будете реализовывать интерфейс слушателя канвы. Следовательно, можете продолжать передавать себя в конструктор, а метод интерфейса у нас уже правильно реализован, с верной сигнатурой. Чтобы подчеркнуть, что это реализация интерфейса, допишем аннотацию оверрайд. \\ \hline
|
||||||
|
|
||||||
|
06-27 & Насладимся летающими шариками в одном приложении, и летающими квадратиками в другом. Теперь на основе нашего очень хорошо отделённого интерфейсами общего пакета можно штамповать такие приложения практически без усилий. Понимаете, как разработчики в игровых студиях делают по сотне очень похожих игр в год? \\ \hline
|
||||||
|
|
||||||
|
06-28 & Дефолтная реализация интерфейса \\ \hline
|
||||||
|
& \\ \hline
|
||||||
|
& \\ \hline
|
||||||
|
|
||||||
отбивка Анонимные классы & Программные интерфейсы открывают перед разработчиком широчайшие возможности по написанию более выразительного кода. Одна из наиболее часто используемых возможностей - анонимные классы. \\ \hline
|
отбивка Анонимные классы & Программные интерфейсы открывают перед разработчиком широчайшие возможности по написанию более выразительного кода. Одна из наиболее часто используемых возможностей - анонимные классы. \\ \hline
|
||||||
|
|
||||||
|
@ -84,12 +129,68 @@
|
||||||
Понятен-ли этот синтаксис? Это создание объекта анонимного класса, никак не называющегося, реализующего интерфейс.
|
Понятен-ли этот синтаксис? Это создание объекта анонимного класса, никак не называющегося, реализующего интерфейс.
|
||||||
Тут можно поговорить о лямбдах, для того чтобы сократить синтаксис мы можем просто убрать то что неизменно для этого анонимного класса - название интерфейса, название метода и класс аргумента. \\ \hline
|
Тут можно поговорить о лямбдах, для того чтобы сократить синтаксис мы можем просто убрать то что неизменно для этого анонимного класса - название интерфейса, название метода и класс аргумента. \\ \hline
|
||||||
|
|
||||||
|
|
||||||
& \\ \hline
|
& \\ \hline
|
||||||
& \\ \hline
|
& \\ \hline
|
||||||
& \\ \hline
|
& \\ \hline
|
||||||
|
|
||||||
\end{longtable}
|
\end{longtable}
|
||||||
|
|
||||||
|
\begin{figure}[H]
|
||||||
|
\centering
|
||||||
|
\fontsize{12}{1}\selectfont
|
||||||
|
\includesvg[scale=1.01]{pics/jd-02-interfaces-use.svg}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
%\scalebox{.45}{\input{pics/jd-02-bkg-sine.pgf}}
|
||||||
|
|
||||||
|
\begin{forest}
|
||||||
|
for tree={
|
||||||
|
font=\ttfamily, grow'=0, child anchor=west,
|
||||||
|
parent anchor=south, anchor=west, calign=first,
|
||||||
|
edge path={
|
||||||
|
\noexpand\path [draw, \forestoption{edge}]
|
||||||
|
(!u.south west) +(7.5pt,0) |- node[fill,inner sep=1.5pt]
|
||||||
|
{} (.child anchor)\forestoption{edge label};
|
||||||
|
}, before typesetting nodes={
|
||||||
|
if n=1 {insert before={[,phantom]}} {} },
|
||||||
|
fit=band, before computing xy={l=20pt},
|
||||||
|
}
|
||||||
|
[JDKit
|
||||||
|
[src/ru.gb.jdk.two.online
|
||||||
|
[bricks
|
||||||
|
[Brick]
|
||||||
|
[MainWindow]
|
||||||
|
]
|
||||||
|
[circles
|
||||||
|
[Background]
|
||||||
|
[Ball]
|
||||||
|
[MainWindow]
|
||||||
|
]
|
||||||
|
[common
|
||||||
|
[Interactable]
|
||||||
|
[MainCanvas]
|
||||||
|
[Sprite]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
[README.md]
|
||||||
|
]
|
||||||
|
\end{forest}
|
||||||
|
|
||||||
\end{document}
|
\end{document}
|
||||||
|
|
||||||
|
|
||||||
|
дз -- динамичкески расширяемый массив и слушатели кнопок. подводка: Как известно, в джава все массивы имеют неизменяемую размерность. Это накладывает некоторые архитектурные ограничения на программиста, но мы ж с вами крутые программисты, вон сколько лекций и семинаров позади, можем обмануть систему. Код не сложный, когда старый массив заполнился, просто увеличиваем его в два раза и переносим шарики из старого в новый
|
||||||
|
|
||||||
|
|
||||||
****** Вернёмся к нашим кружочкам
|
****** Вернёмся к нашим кружочкам
|
||||||
Смотрим прям первый метод, invokeLater() он принимает на вход какой-то Runnable. Идём в Runnable и видим, что это интерфейс, который реализует один единственный метод run(). Получается, что мы в invokeLater передаём новый экземпляр анонимного класса который РЕАЛИЗУЕТ ИНТЕРФЕЙС Runnable, вот описание этого класса, мы в нём переопределяем метод run. Вот так это читается. Ровно тоже самое мы сделали с mouseListener. Здесь немного сложнее. Есть интерфейс MouseListener в котором описаны вот эти все методы. И есть специальный класс MouseAdapter в котором все эти методы уже реализованы. Реализации пустые, но они есть, поэтому мы можем не все методы оверрайдить, а только те, которые посчитаем нужными. И когда мы этот MouseAdapter отдаём нашему методу, мы говорим: создай нам новый экземпляр анонимного класса, который НАСЛЕДУЕТСЯ ОТ КЛАССА MouseAdapter и переопредели вот этот метод. Остальные оставляй пустыми. Чувствуете разницу? Как можно избежать таких конструкций и при этом получить понятный код без лишних заморочек? Очень просто. Скажем, что наш класс - реализует тот или иной интерфейс, и переопределим все методы. В некоторые из них даже напишем реализацию, и туда, где требуется интерфейс - передадим себя. Мы же теперь MouseListener, да и Runnable.
|
Смотрим прям первый метод, invokeLater() он принимает на вход какой-то Runnable. Идём в Runnable и видим, что это интерфейс, который реализует один единственный метод run(). Получается, что мы в invokeLater передаём новый экземпляр анонимного класса который РЕАЛИЗУЕТ ИНТЕРФЕЙС Runnable, вот описание этого класса, мы в нём переопределяем метод run. Вот так это читается. Ровно тоже самое мы сделали с mouseListener. Здесь немного сложнее. Есть интерфейс MouseListener в котором описаны вот эти все методы. И есть специальный класс MouseAdapter в котором все эти методы уже реализованы. Реализации пустые, но они есть, поэтому мы можем не все методы оверрайдить, а только те, которые посчитаем нужными. И когда мы этот MouseAdapter отдаём нашему методу, мы говорим: создай нам новый экземпляр анонимного класса, который НАСЛЕДУЕТСЯ ОТ КЛАССА MouseAdapter и переопредели вот этот метод. Остальные оставляй пустыми. Чувствуете разницу? Как можно избежать таких конструкций и при этом получить понятный код без лишних заморочек? Очень просто. Скажем, что наш класс - реализует тот или иной интерфейс, и переопределим все методы. В некоторые из них даже напишем реализацию, и туда, где требуется интерфейс - передадим себя. Мы же теперь MouseListener, да и Runnable.
|
||||||
|
|
||||||
|
|
||||||
|
исключения
|
||||||
|
06-29 & Осталось коротко поговорить о некоторых особенностях работы приложений, использующих графические интерфейсы. \\ \hline
|
||||||
|
|
||||||
|
06-30 & Поскольку графический оконный интерфейс - это всегда многопоточность, да и привычного нам терминала под рукой нет, то тут сразу возникают особенности с обработкой исключений. Как ловить? Как показывать? Вот, например, есть у нас какое-то окно, на котором есть кнопка. У кнопки есть обработчик, в котором что-то идёт не так, скажем, выход за пределы массива. достаточно типичная ситуация. Как
|
||||||
|
|
||||||
|
|
||||||
|
Аннотации?
|
Loading…
Reference in New Issue