You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

806 lines
74 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<!--
==============================================================================
"GitHub HTML5 Pandoc Template" v2.1 — by Tristano Ajmone
==============================================================================
Copyright © Tristano Ajmone, 2017, MIT License (MIT). Project's home:
- https://github.com/tajmone/pandoc-goodies
The CSS in this template reuses source code taken from the following projects:
- GitHub Markdown CSS: Copyright © Sindre Sorhus, MIT License (MIT):
https://github.com/sindresorhus/github-markdown-css
- Primer CSS: Copyright © 2016-2017 GitHub Inc., MIT License (MIT):
http://primercss.io/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The MIT License
Copyright (c) Tristano Ajmone, 2017 (github.com/tajmone/pandoc-goodies)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Copyright (c) 2017 GitHub Inc.
"GitHub Pandoc HTML5 Template" is Copyright (c) Tristano Ajmone, 2017, released
under the MIT License (MIT); it contains readaptations of substantial portions
of the following third party softwares:
(1) "GitHub Markdown CSS", Copyright (c) Sindre Sorhus, MIT License (MIT).
(2) "Primer CSS", Copyright (c) 2016 GitHub Inc., MIT License (MIT).
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
==============================================================================-->
<html>
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<meta name="author" content="Laurent Provot" />
<title>Introduction à Kotlin</title>
<style type="text/css">
.markdown-body{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;color:#24292e;font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:16px;line-height:1.5;word-wrap:break-word;box-sizing:border-box;min-width:200px;max-width:980px;margin:0 auto;padding:45px}.markdown-body a{color:#0366d6;background-color:transparent;text-decoration:none;-webkit-text-decoration-skip:objects}.markdown-body a:active,.markdown-body a:hover{outline-width:0}.markdown-body a:hover{text-decoration:underline}.markdown-body a:not([href]){color:inherit;text-decoration:none}.markdown-body strong{font-weight:600}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:24px;margin-bottom:16px;font-weight:600;line-height:1.25}.markdown-body h1{font-size:2em;margin:.67em 0;padding-bottom:.3em;border-bottom:1px solid #eaecef}.markdown-body h2{padding-bottom:.3em;font-size:1.5em;border-bottom:1px solid #eaecef}.markdown-body h3{font-size:1.25em}.markdown-body h4{font-size:1em}.markdown-body h5{font-size:.875em}.markdown-body h6{font-size:.85em;color:#6a737d}.markdown-body img{border-style:none}.markdown-body svg:not(:root){overflow:hidden}.markdown-body hr{box-sizing:content-box;height:.25em;margin:24px 0;padding:0;overflow:hidden;background-color:#e1e4e8;border:0}.markdown-body hr::before{display:table;content:""}.markdown-body hr::after{display:table;clear:both;content:""}.markdown-body input{margin:0;overflow:visible;font:inherit;font-family:inherit;font-size:inherit;line-height:inherit}.markdown-body [type=checkbox]{box-sizing:border-box;padding:0}.markdown-body *{box-sizing:border-box}.markdown-body blockquote{margin:0}.markdown-body ol,.markdown-body ul{padding-left:2em}.markdown-body ol ol,.markdown-body ul ol{list-style-type:lower-roman}.markdown-body ol ol,.markdown-body ol ul,.markdown-body ul ol,.markdown-body ul ul{margin-top:0;margin-bottom:0}.markdown-body ol ol ol,.markdown-body ol ul ol,.markdown-body ul ol ol,.markdown-body ul ul ol{list-style-type:lower-alpha}.markdown-body li>p{margin-top:16px}.markdown-body li+li{margin-top:.25em}.markdown-body dd{margin-left:0}.markdown-body dl{padding:0}.markdown-body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:600}.markdown-body dl dd{padding:0 16px;margin-bottom:16px}.markdown-body code{font-family:SFMono-Regular,Consolas,"Liberation Mono",Menlo,Courier,monospace}.markdown-body pre{font:12px SFMono-Regular,Consolas,"Liberation Mono",Menlo,Courier,monospace;word-wrap:normal}.markdown-body blockquote,.markdown-body dl,.markdown-body ol,.markdown-body p,.markdown-body pre,.markdown-body table,.markdown-body ul{margin-top:0;margin-bottom:16px}.markdown-body blockquote{padding:0 1em;color:#6a737d;border-left:.25em solid #dfe2e5}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body table{display:block;width:100%;overflow:auto;border-spacing:0;border-collapse:collapse}.markdown-body table th{font-weight:600}.markdown-body table td,.markdown-body table th{padding:6px 13px;border:1px solid #dfe2e5}.markdown-body table tr{background-color:#fff;border-top:1px solid #c6cbd1}.markdown-body table tr:nth-child(2n){background-color:#f6f8fa}.markdown-body img{max-width:100%;box-sizing:content-box;background-color:#fff}.markdown-body code{padding:.2em 0;margin:0;font-size:85%;background-color:rgba(27,31,35,.05);border-radius:3px}.markdown-body code::after,.markdown-body code::before{letter-spacing:-.2em;content:"\00a0"}.markdown-body pre>code{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;background:0 0;border:0}.markdown-body .highlight{margin-bottom:16px}.markdown-body .highlight pre{margin-bottom:0;word-break:normal}.markdown-body .highlight pre,.markdown-body pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f6f8fa;border-radius:3px}.markdown-body pre code{display:inline;max-width:auto;padding:0;margin:0;overflow:visible;line-height:inherit;word-wrap:normal;background-color:transparent;border:0}.markdown-body pre code::after,.markdown-body pre code::before{content:normal}.markdown-body .full-commit .btn-outline:not(:disabled):hover{color:#005cc5;border-color:#005cc5}.markdown-body kbd{box-shadow:inset 0 -1px 0 #959da5;display:inline-block;padding:3px 5px;font:11px/10px SFMono-Regular,Consolas,"Liberation Mono",Menlo,Courier,monospace;color:#444d56;vertical-align:middle;background-color:#fcfcfc;border:1px solid #c6cbd1;border-bottom-color:#959da5;border-radius:3px;box-shadow:inset 0 -1px 0 #959da5}.markdown-body :checked+.radio-label{position:relative;z-index:1;border-color:#0366d6}.markdown-body .task-list-item{list-style-type:none}.markdown-body .task-list-item+.task-list-item{margin-top:3px}.markdown-body .task-list-item input{margin:0 .2em .25em -1.6em;vertical-align:middle}.markdown-body::before{display:table;content:""}.markdown-body::after{display:table;clear:both;content:""}.markdown-body>:first-child{margin-top:0!important}.markdown-body>:last-child{margin-bottom:0!important}.Alert,.Error,.Note,.Success,.Warning{padding:11px;margin-bottom:24px;border-style:solid;border-width:1px;border-radius:4px}.Alert p,.Error p,.Note p,.Success p,.Warning p{margin-top:0}.Alert p:last-child,.Error p:last-child,.Note p:last-child,.Success p:last-child,.Warning p:last-child{margin-bottom:0}.Alert{color:#246;background-color:#e2eef9;border-color:#bac6d3}.Warning{color:#4c4a42;background-color:#fff9ea;border-color:#dfd8c2}.Error{color:#911;background-color:#fcdede;border-color:#d2b2b2}.Success{color:#22662c;background-color:#e2f9e5;border-color:#bad3be}.Note{color:#2f363d;background-color:#f6f8fa;border-color:#d5d8da}.Alert h1,.Alert h2,.Alert h3,.Alert h4,.Alert h5,.Alert h6{color:#246;margin-bottom:0}.Warning h1,.Warning h2,.Warning h3,.Warning h4,.Warning h5,.Warning h6{color:#4c4a42;margin-bottom:0}.Error h1,.Error h2,.Error h3,.Error h4,.Error h5,.Error h6{color:#911;margin-bottom:0}.Success h1,.Success h2,.Success h3,.Success h4,.Success h5,.Success h6{color:#22662c;margin-bottom:0}.Note h1,.Note h2,.Note h3,.Note h4,.Note h5,.Note h6{color:#2f363d;margin-bottom:0}.Alert h1:first-child,.Alert h2:first-child,.Alert h3:first-child,.Alert h4:first-child,.Alert h5:first-child,.Alert h6:first-child,.Error h1:first-child,.Error h2:first-child,.Error h3:first-child,.Error h4:first-child,.Error h5:first-child,.Error h6:first-child,.Note h1:first-child,.Note h2:first-child,.Note h3:first-child,.Note h4:first-child,.Note h5:first-child,.Note h6:first-child,.Success h1:first-child,.Success h2:first-child,.Success h3:first-child,.Success h4:first-child,.Success h5:first-child,.Success h6:first-child,.Warning h1:first-child,.Warning h2:first-child,.Warning h3:first-child,.Warning h4:first-child,.Warning h5:first-child,.Warning h6:first-child{margin-top:0}h1.title,p.subtitle{text-align:center}h1.title.followed-by-subtitle{margin-bottom:0}p.subtitle{font-size:1.5em;font-weight:600;line-height:1.25;margin-top:0;margin-bottom:16px;padding-bottom:.3em}div.line-block{white-space:pre-line}
</style>
<style type="text/css">code{white-space: pre;}</style>
<style type="text/css">
a.sourceLine { display: inline-block; line-height: 1.25; }
a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
a.sourceLine:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode { white-space: pre; position: relative; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
code.sourceCode { white-space: pre-wrap; }
a.sourceLine { text-indent: -1em; padding-left: 1em; }
}
pre.numberSource a.sourceLine
{ position: relative; left: -4em; }
pre.numberSource a.sourceLine::before
{ content: attr(data-line-number);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; pointer-events: all; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
a.sourceLine::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
</style>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<article class="markdown-body">
<header>
<!--<h1 class="title">Introduction à Kotlin</h1>-->
<p class="date">Septembre 2022</p>
</header>
<h1 id="introduction-à-kotlin">Introduction à Kotlin</h1>
<h2 id="pourquoi-kotlin">Pourquoi Kotlin</h2>
<ul>
<li>Google I/O 2017 : langage de premier ordre pour Android</li>
<li><p>Intégré par défaut à partir dAndroid Studio 3.0</p></li>
<li>Langage à typage statique</li>
<li>Sexécute sur une JVM (et par extension sur ART)</li>
<li>Beaucoup dinférence de type, donc moins verbeux que Java</li>
<li>Multiparadigme (procedural, fonctionnel, orienté objets)</li>
<li><p>Pousse aux <em>best practices</em></p></li>
</ul>
<p>Pour lauto-apprentissage : <a href="https://kotlinlang.org/docs/home.html" class="uri">https://kotlinlang.org/docs/home.html</a><a href="https://play.kotlinlang.org/" class="uri">https://play.kotlinlang.org/</a></p>
<h2 id="règles-de-base">Règles de base</h2>
<ul>
<li>Code contenu dans des fichiers <code>.kt</code></li>
<li>Pas besoin de <code>;</code> en fin de ligne</li>
</ul>
<div class="sourceCode" id="cb1"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb1-1" data-line-number="1"><span class="kw">fun</span> <span class="fu">main</span>(<span class="va">args</span>: <span class="dt">Array</span>&lt;<span class="va">String</span>&gt;) {</a>
<a class="sourceLine" id="cb1-2" data-line-number="2"> println(<span class="st">&quot;Hello Kotlin&quot;</span>)</a>
<a class="sourceLine" id="cb1-3" data-line-number="3">}</a></code></pre></div>
<ul>
<li>Déclarations à la UML</li>
<li>Conventions de nommage très similaires à Java<br />
cf. <a href="https://kotlinlang.org/docs/coding-conventions.html" class="uri">https://kotlinlang.org/docs/coding-conventions.html</a></li>
</ul>
<h2 id="types">Types</h2>
<ul>
<li>Pas de types primitifs</li>
<li>Action sans résultat : singleton <code>Unit</code> (≈<code>void</code> de Java)</li>
<li>Rien, fonction qui ne termine pas normalement : <code>Nothing</code></li>
<li>Nombres : <code>Double</code>, <code>Float</code>, <code>Long</code>, <code>Int</code>, <code>Short</code>, <code>Byte</code></li>
<li>Pas de conversions implicite : <code>toInt()</code>, <code>toFloat()</code>, …</li>
<li>Littéraux : comme en Java (<code>0b101010</code>, <code>0xB8</code>, <code>12</code>, <code>3.14f</code>)</li>
<li>Possibilité de séparateur <code>1_000_000</code></li>
<li>Booléens : <code>Boolean</code> (<code>true</code> et <code>false</code>)</li>
<li><p>Tableaux : classe <code>Array</code> (<code>get</code>, <code>set</code>, <code>[]</code>, <code>size</code>) + fonctions</p></li>
<li>Texte : <code>Char</code>, <code>String</code></li>
<li>Les chaînes de caractères sont <em>immuables</em></li>
<li><code>&quot;Hello\tTab&quot;</code> (escaped string) ou <code>&quot;&quot;&quot; avec saut de lignes &quot;&quot;&quot;</code> (raw string)</li>
<li><p>Utilisation possible de <em>string templates</em> :</p></li>
</ul>
<div class="sourceCode" id="cb2"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb2-1" data-line-number="1"><span class="kw">val</span> <span class="va">name</span> = <span class="st">&quot;Laurent&quot;</span></a>
<a class="sourceLine" id="cb2-2" data-line-number="2"><span class="kw">val</span> <span class="va">greetings</span> = <span class="st">&quot;Salut $name !&quot;</span></a>
<a class="sourceLine" id="cb2-3" data-line-number="3"><span class="kw">val</span> <span class="va">scream</span> = <span class="st">&quot;EH HO… ${name.toUpperCase()} !&quot;</span></a></code></pre></div>
<h2 id="références">Références</h2>
<ul>
<li><p><code>val</code> : reférence une valeur constante (immuable)</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb3-1" data-line-number="1"><span class="kw">val</span> <span class="va">answer</span> : <span class="kw">Int</span> = <span class="dv">42</span></a>
<a class="sourceLine" id="cb3-2" data-line-number="2"><span class="kw">val</span> <span class="va">age</span> = <span class="dv">33</span>; <span class="co">// Type inféré</span></a>
<a class="sourceLine" id="cb3-3" data-line-number="3"><span class="kw">val</span> <span class="va">what</span>: <span class="kw">String</span> <span class="co">// Type nécessaire si pas d&#39;initialisation</span></a>
<a class="sourceLine" id="cb3-4" data-line-number="4">what = <span class="st">&quot;Whaaat ?&quot;</span> <span class="co">// Initialisation différée</span></a>
<a class="sourceLine" id="cb3-5" data-line-number="5"></a>
<a class="sourceLine" id="cb3-6" data-line-number="6">age += <span class="dv">2</span> <span class="co">// Erreur, pas modifiable</span></a></code></pre></div></li>
<li><p><code>var</code> : reférence une variable (peu changer de valeur)</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb4-1" data-line-number="1"><span class="kw">var</span> <span class="va">x</span> : <span class="kw">Int</span> = <span class="dv">2</span>;</a>
<a class="sourceLine" id="cb4-2" data-line-number="2"><span class="kw">var</span> <span class="va">y</span> = <span class="ch">&#39;y&#39;</span>;</a>
<a class="sourceLine" id="cb4-3" data-line-number="3">++x; <span class="co">// OK, muable</span></a></code></pre></div></li>
<li><p><code>const</code> : constante connue à la compilation</p>
<ul>
<li>soit top level, soit membre dun <code>object</code></li>
<li>initialisée avec une <code>String</code> ou un valeur primitive</li>
<li>pas de getter personnalisé</li>
</ul>
<div class="sourceCode" id="cb5"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb5-1" data-line-number="1">const <span class="kw">val</span> <span class="va">PI_APPROX</span>: float = <span class="fl">3.14f</span>;</a></code></pre></div></li>
<li><p>Comparaison de références</p>
<ul>
<li><code>==</code> comparaison structurelle (<code>equals()</code>)</li>
<li><code>===</code> comparaison dinstances (emplacement mémoire)</li>
</ul></li>
</ul>
<h2 id="nullable-types">Nullable types</h2>
<ul>
<li>Nullable : <code>Double?</code>, <code>String?</code>, …</li>
<li>Pour éviter les <code>NullPointerException</code> (NPE)</li>
<li><code>?.</code> pour un accès sûr</li>
<li>Elvis operator : <code>?:</code></li>
</ul>
<div class="sourceCode" id="cb6"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb6-1" data-line-number="1"><span class="kw">val</span> <span class="va">l</span>: <span class="kw">Int</span> = <span class="cf">if</span> (b != <span class="kw">null</span>) b.length <span class="cf">else</span> <span class="dv">-1</span></a>
<a class="sourceLine" id="cb6-2" data-line-number="2"><span class="co">// équivalent</span></a>
<a class="sourceLine" id="cb6-3" data-line-number="3"><span class="kw">val</span> <span class="va">l</span> = b?.length ?: <span class="dv">-1</span></a></code></pre></div>
<ul>
<li>Forçage : <code>!!.</code> lève une NPE si lobjet est <code>null</code> (à éviter !)</li>
</ul>
<h2 id="les-intervalles-range">Les intervalles (Range)</h2>
<ul>
<li>Opérateur <code>..</code> (issu de la fonction <code>rangeTo()</code>)</li>
<li>Fonctions extensions : <code>until</code>, <code>downTo</code>, <code>step</code></li>
</ul>
<div class="sourceCode" id="cb7"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb7-1" data-line-number="1"><span class="dv">1</span>..<span class="dv">10</span> <span class="co">// de 1 inclus jusqu&#39;à 10 inclus</span></a>
<a class="sourceLine" id="cb7-2" data-line-number="2"><span class="dv">1</span> until <span class="dv">10</span> <span class="co">// de 1 inclus jusqu&#39;à 10 exclus</span></a>
<a class="sourceLine" id="cb7-3" data-line-number="3"><span class="dv">4</span>..<span class="dv">1</span> <span class="co">// vide</span></a>
<a class="sourceLine" id="cb7-4" data-line-number="4"><span class="dv">4</span> downto <span class="dv">1</span> <span class="co">// 4, 3, 2, 1</span></a>
<a class="sourceLine" id="cb7-5" data-line-number="5"><span class="dv">10</span> downto <span class="dv">1</span> step <span class="dv">2</span> <span class="co">// 10, 8, 6, 4, 2</span></a></code></pre></div>
<ul>
<li><code>step</code> doit être strictement positif</li>
</ul>
<h2 id="le-transtypage-cast">Le transtypage (cast)</h2>
<ul>
<li>Savoir si un objet est dun certain type : <code>is</code></li>
</ul>
<div class="sourceCode" id="cb8"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb8-1" data-line-number="1"><span class="cf">if</span> (obj <span class="kw">is</span> <span class="kw">String</span>) {</a>
<a class="sourceLine" id="cb8-2" data-line-number="2"> print(obj.trim())</a>
<a class="sourceLine" id="cb8-3" data-line-number="3">}</a>
<a class="sourceLine" id="cb8-4" data-line-number="4"></a>
<a class="sourceLine" id="cb8-5" data-line-number="5"><span class="cf">if</span> (obj !<span class="kw">is</span> <span class="kw">String</span>) { <span class="co">// equivalent à !(obj is String)</span></a>
<a class="sourceLine" id="cb8-6" data-line-number="6"> print(<span class="st">&quot;Not a String&quot;</span>)</a>
<a class="sourceLine" id="cb8-7" data-line-number="7">}</a>
<a class="sourceLine" id="cb8-8" data-line-number="8"><span class="cf">else</span> {</a>
<a class="sourceLine" id="cb8-9" data-line-number="9"> print(obj.length)</a>
<a class="sourceLine" id="cb8-10" data-line-number="10">}</a></code></pre></div>
<ul>
<li>Cast explicite souvent inutile : le compilateur sen occupe (smart cast)</li>
</ul>
<div class="sourceCode" id="cb9"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb9-1" data-line-number="1"><span class="co">// x est automatiquement casté en String à droite du ||</span></a>
<a class="sourceLine" id="cb9-2" data-line-number="2"><span class="cf">if</span> (x !<span class="kw">is</span> <span class="kw">String</span> || x.length == <span class="dv">0</span>) <span class="kw">return</span></a>
<a class="sourceLine" id="cb9-3" data-line-number="3"></a>
<a class="sourceLine" id="cb9-4" data-line-number="4"><span class="co">// x est automatiquement casté en String à droite du &amp;&amp; et dans le if</span></a>
<a class="sourceLine" id="cb9-5" data-line-number="5"><span class="cf">if</span> (x <span class="kw">is</span> <span class="kw">String</span> &amp;&amp; x.length &gt; <span class="dv">0</span>) {</a>
<a class="sourceLine" id="cb9-6" data-line-number="6"> print(x.length)</a>
<a class="sourceLine" id="cb9-7" data-line-number="7">}</a></code></pre></div>
<ul>
<li>On peut néamoins caster avec <code>as</code> (unsafe cast)</li>
<li>Lève une exception si pas possible</li>
</ul>
<div class="sourceCode" id="cb10"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb10-1" data-line-number="1"><span class="kw">val</span> <span class="va">x</span>: <span class="kw">String</span> = y <span class="kw">as</span> <span class="kw">String</span></a></code></pre></div>
<ul>
<li>Utiliser <code>as?</code> pour safe cast</li>
<li>Le résultat est un nullable type</li>
</ul>
<div class="sourceCode" id="cb11"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb11-1" data-line-number="1"><span class="kw">val</span> <span class="va">x</span>: <span class="kw">String</span>? = y <span class="kw">as</span>? <span class="kw">String</span></a></code></pre></div>
<h2 id="contrôle-du-flot-dexécution">Contrôle du flot dexécution</h2>
<ul>
<li><code>if</code>, <code>while</code>, <code>break</code>, <code>continue</code> : comme en Java</li>
<li>possibilité de labels : <code>unLabel@</code><code>break@unLabel</code></li>
</ul>
<div class="sourceCode" id="cb12"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb12-1" data-line-number="1">loop@ <span class="cf">for</span> (i <span class="kw">in</span> <span class="dv">1</span>..<span class="dv">100</span>) {</a>
<a class="sourceLine" id="cb12-2" data-line-number="2"> <span class="cf">for</span> (j <span class="kw">in</span> <span class="dv">1</span>..<span class="dv">100</span>) {</a>
<a class="sourceLine" id="cb12-3" data-line-number="3"> <span class="cf">if</span> (…) break<span class="at">@loop</span></a>
<a class="sourceLine" id="cb12-4" data-line-number="4"> }</a>
<a class="sourceLine" id="cb12-5" data-line-number="5">}</a></code></pre></div>
<ul>
<li><code>when</code> : équivalent du <code>switch</code> (mais plus sympa)</li>
</ul>
<div class="sourceCode" id="cb13"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb13-1" data-line-number="1"><span class="cf">when</span> (x) {</a>
<a class="sourceLine" id="cb13-2" data-line-number="2"> <span class="dv">0</span>, <span class="dv">1</span> -&gt; print(<span class="st">&quot;peu&quot;</span>)</a>
<a class="sourceLine" id="cb13-3" data-line-number="3"> <span class="kw">in</span> <span class="dv">2</span>..<span class="dv">10</span> -&gt; print(<span class="st">&quot;moyen&quot;</span>)</a>
<a class="sourceLine" id="cb13-4" data-line-number="4"> <span class="kw">is</span> <span class="kw">String</span> -&gt; print(<span class="st">&quot;${x.trim()} est une String&quot;</span>)</a>
<a class="sourceLine" id="cb13-5" data-line-number="5"> <span class="cf">else</span> -&gt; {</a>
<a class="sourceLine" id="cb13-6" data-line-number="6"> println(<span class="st">&quot;rien de tout ça&quot;</span>)</a>
<a class="sourceLine" id="cb13-7" data-line-number="7"> print(<span class="st">&quot;on peu mettre un block&quot;</span>)</a>
<a class="sourceLine" id="cb13-8" data-line-number="8"> }</a>
<a class="sourceLine" id="cb13-9" data-line-number="9">}</a></code></pre></div>
<div class="sourceCode" id="cb14"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb14-1" data-line-number="1">println(</a>
<a class="sourceLine" id="cb14-2" data-line-number="2"> <span class="cf">when</span> {</a>
<a class="sourceLine" id="cb14-3" data-line-number="3"> x.isOdd() -&gt; <span class="st">&quot;impair&quot;</span></a>
<a class="sourceLine" id="cb14-4" data-line-number="4"> x.isEven() -&gt; <span class="st">&quot;pair&quot;</span></a>
<a class="sourceLine" id="cb14-5" data-line-number="5"> <span class="cf">else</span> -&gt; <span class="st">&quot;bizarre&quot;</span></a>
<a class="sourceLine" id="cb14-6" data-line-number="6">})</a></code></pre></div>
<ul>
<li><code>when</code> et <code>if</code> peuvent êrte utilisées comme expressions : elles renvoient comme valeur le resultat de leur dernière instruction exécutée</li>
<li><code>for</code> : parcours sur tout ce qui fournit un itérateur (<code>foreach</code> de C#), i.e. :
<ul>
<li>fournit une méthode <code>iterator()</code></li>
<li>cet itérateur a une méthode <code>next()</code> et une méthode <code>hasNext()</code> qui retourne un <code>Boolean</code> (doivent être marquées <code>operator</code>)</li>
</ul></li>
<li>Itération classique (intervalle, String, Array, …)</li>
</ul>
<div class="sourceCode" id="cb15"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb15-1" data-line-number="1"><span class="cf">for</span> (i <span class="kw">in</span> <span class="dv">0</span>..<span class="dv">9</span>) {</a>
<a class="sourceLine" id="cb15-2" data-line-number="2"> println(i)</a>
<a class="sourceLine" id="cb15-3" data-line-number="3">}</a>
<a class="sourceLine" id="cb15-4" data-line-number="4"><span class="cf">for</span> (c <span class="kw">in</span> <span class="st">&quot;Hello&quot;</span>) {</a>
<a class="sourceLine" id="cb15-5" data-line-number="5"> println(c)</a>
<a class="sourceLine" id="cb15-6" data-line-number="6">}</a></code></pre></div>
<ul>
<li>Itération avec indices</li>
</ul>
<div class="sourceCode" id="cb16"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb16-1" data-line-number="1"><span class="cf">for</span> (i <span class="kw">in</span> array.indices) {</a>
<a class="sourceLine" id="cb16-2" data-line-number="2"> println(array[i])</a>
<a class="sourceLine" id="cb16-3" data-line-number="3">}</a>
<a class="sourceLine" id="cb16-4" data-line-number="4"></a>
<a class="sourceLine" id="cb16-5" data-line-number="5"><span class="cf">for</span> ((index, value) <span class="kw">in</span> array.withIndex()) {</a>
<a class="sourceLine" id="cb16-6" data-line-number="6"> println(<span class="st">&quot;The element at $index is $value&quot;</span>)</a>
<a class="sourceLine" id="cb16-7" data-line-number="7">}</a></code></pre></div>
<ul>
<li>Pour les execptions : comme en Java (sauf quil nexiste pas de notion de <em>checked exception</em>)</li>
<li><code>try/catch/finally</code> est un expression</li>
</ul>
<h2 id="les-fonctions">Les fonctions</h2>
<ul>
<li>Possibilité de fonction <em>top level</em> (pas forcément membre dun objet)</li>
</ul>
<div class="sourceCode" id="cb17"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb17-1" data-line-number="1"><span class="kw">fun</span> <span class="fu">sum</span>(<span class="va">a</span>: <span class="dt">Int</span>, <span class="va">b</span>: <span class="dt">Int</span>): <span class="dt">Int</span> {</a>
<a class="sourceLine" id="cb17-2" data-line-number="2"> <span class="kw">return</span> a + b</a>
<a class="sourceLine" id="cb17-3" data-line-number="3">}</a></code></pre></div>
<ul>
<li>Avec inférence du type de retour pour les <em>expression body</em> (pratique pour getter/setter)</li>
</ul>
<div class="sourceCode" id="cb18"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb18-1" data-line-number="1"><span class="kw">fun</span> <span class="fu">sum</span>(<span class="va">a</span>: <span class="dt">Int</span>, <span class="va">b</span>: <span class="dt">Int</span>) = a + b</a></code></pre></div>
<ul>
<li>Paramètres avec valeur par défaut (pratique pour les Ctor)</li>
</ul>
<div class="sourceCode" id="cb19"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb19-1" data-line-number="1"><span class="kw">fun</span> <span class="fu">say</span>(<span class="va">text</span>: <span class="dt">String</span> = <span class="st">&quot;Something&quot;</span>) = println(text)</a>
<a class="sourceLine" id="cb19-2" data-line-number="2">say() <span class="co">// Affiche Something</span></a>
<a class="sourceLine" id="cb19-3" data-line-number="3">say(<span class="st">&quot;Hi guys&quot;</span>) <span class="co">// Affiche Hi guys</span></a></code></pre></div>
<ul>
<li>Paramètres nommés</li>
</ul>
<div class="sourceCode" id="cb20"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb20-1" data-line-number="1"><span class="kw">fun</span> <span class="fu">Box</span>.<span class="fu">setMargins</span>(<span class="va">left</span>: <span class="dt">Int</span>, <span class="va">top</span>: <span class="dt">Int</span>, <span class="va">right</span>: <span class="dt">Int</span>, <span class="va">bottom</span>: <span class="dt">Int</span>) { … }</a>
<a class="sourceLine" id="cb20-2" data-line-number="2"></a>
<a class="sourceLine" id="cb20-3" data-line-number="3">myBox.setMargins(<span class="dv">10</span>,<span class="dv">10</span>,<span class="dv">20</span>,<span class="dv">20</span>) <span class="co">// haut ? bas ? gauche ? droite ?</span></a>
<a class="sourceLine" id="cb20-4" data-line-number="4">myBox.setMargins(left = <span class="dv">10</span>, right = <span class="dv">10</span>, top = <span class="dv">20</span>, bottom = <span class="dv">20</span>)</a></code></pre></div>
<ul>
<li>Paramètres variables (<code>Type...</code> de Java)</li>
<li>Utilisation du <em>spread</em> operator (*) pour paramètres nommés</li>
</ul>
<div class="sourceCode" id="cb21"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb21-1" data-line-number="1"><span class="kw">fun</span> <span class="fu">foo</span>(<span class="kw">vararg</span> <span class="va">strings</span>: <span class="dt">String</span>) { … }</a>
<a class="sourceLine" id="cb21-2" data-line-number="2">foo(<span class="st">&quot;s1&quot;</span>, <span class="st">&quot;s2&quot;</span>)</a>
<a class="sourceLine" id="cb21-3" data-line-number="3">foo(strings = *arrayOf(<span class="st">&quot;a&quot;</span>, <span class="st">&quot;b&quot;</span>, <span class="st">&quot;c&quot;</span>))</a></code></pre></div>
<ul>
<li>On peut déclarer une fonction dans une autre fonction</li>
<li>Utile pour récursivité terminale</li>
</ul>
<div class="sourceCode" id="cb22"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb22-1" data-line-number="1"><span class="kw">fun</span> <span class="fu">dfs</span>(<span class="va">graph</span>: <span class="dt">Graph</span>) {</a>
<a class="sourceLine" id="cb22-2" data-line-number="2"> <span class="kw">val</span> <span class="va">visited</span> = HashSet&lt;Vertex&gt;()</a>
<a class="sourceLine" id="cb22-3" data-line-number="3"></a>
<a class="sourceLine" id="cb22-4" data-line-number="4"> <span class="kw">fun</span> <span class="fu">dfs</span>(<span class="va">current</span>: <span class="dt">Vertex</span>) {</a>
<a class="sourceLine" id="cb22-5" data-line-number="5"> <span class="cf">if</span> (!visited.add(current)) <span class="kw">return</span></a>
<a class="sourceLine" id="cb22-6" data-line-number="6"> <span class="cf">for</span> (v <span class="kw">in</span> current.neighbors)</a>
<a class="sourceLine" id="cb22-7" data-line-number="7"> dfs(v)</a>
<a class="sourceLine" id="cb22-8" data-line-number="8"> }</a>
<a class="sourceLine" id="cb22-9" data-line-number="9"></a>
<a class="sourceLine" id="cb22-10" data-line-number="10"> dfs(graph.vertices[<span class="dv">0</span>])</a>
<a class="sourceLine" id="cb22-11" data-line-number="11">}</a></code></pre></div>
<h2 id="classes-et-objets">Classes et objets</h2>
<ul>
<li>Squelette de classe standard en Java (entre POJO et Bean)</li>
</ul>
<div class="sourceCode" id="cb23"><pre class="sourceCode java"><code class="sourceCode java"><a class="sourceLine" id="cb23-1" data-line-number="1"><span class="kw">class</span> Person {</a>
<a class="sourceLine" id="cb23-2" data-line-number="2"> <span class="kw">private</span> <span class="bu">String</span> name;</a>
<a class="sourceLine" id="cb23-3" data-line-number="3"> <span class="kw">private</span> <span class="dt">int</span> age;</a>
<a class="sourceLine" id="cb23-4" data-line-number="4"></a>
<a class="sourceLine" id="cb23-5" data-line-number="5"> <span class="kw">public</span> <span class="fu">Person</span>(<span class="bu">String</span> name, <span class="dt">int</span> age) {</a>
<a class="sourceLine" id="cb23-6" data-line-number="6"> <span class="kw">this</span>.<span class="fu">name</span> = name;</a>
<a class="sourceLine" id="cb23-7" data-line-number="7"> <span class="kw">this</span>.<span class="fu">age</span> = age;</a>
<a class="sourceLine" id="cb23-8" data-line-number="8"> }</a>
<a class="sourceLine" id="cb23-9" data-line-number="9"></a>
<a class="sourceLine" id="cb23-10" data-line-number="10"> <span class="kw">public</span> <span class="bu">String</span> <span class="fu">getName</span>() { <span class="kw">return</span> name; }</a>
<a class="sourceLine" id="cb23-11" data-line-number="11"> <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setName</span>(<span class="bu">String</span> name) { <span class="kw">this</span>.<span class="fu">name</span> = name; }</a>
<a class="sourceLine" id="cb23-12" data-line-number="12"> <span class="kw">public</span> <span class="bu">String</span> <span class="fu">getAge</span>() { <span class="kw">return</span> age; }</a>
<a class="sourceLine" id="cb23-13" data-line-number="13"> <span class="kw">public</span> <span class="dt">void</span> <span class="fu">setAge</span>(<span class="dt">int</span> age) { <span class="kw">this</span>.<span class="fu">age</span> = age; }</a>
<a class="sourceLine" id="cb23-14" data-line-number="14"></a>
<a class="sourceLine" id="cb23-15" data-line-number="15"> <span class="kw">public</span> <span class="dt">int</span> <span class="fu">hashCode</span>() { … }</a>
<a class="sourceLine" id="cb23-16" data-line-number="16"> <span class="kw">public</span> <span class="dt">boolean</span> <span class="fu">equals</span>() { … }</a>
<a class="sourceLine" id="cb23-17" data-line-number="17"></a>
<a class="sourceLine" id="cb23-18" data-line-number="18"> <span class="at">@Override</span></a>
<a class="sourceLine" id="cb23-19" data-line-number="19"> <span class="kw">public</span> <span class="fu">toString</span>() {</a>
<a class="sourceLine" id="cb23-20" data-line-number="20"> <span class="kw">return</span> <span class="st">&quot;Person(name=&quot;</span> + name + <span class="st">&quot;, age=&quot;</span> + age + <span class="st">&quot;)&quot;</span>;</a>
<a class="sourceLine" id="cb23-21" data-line-number="21"> }</a>
<a class="sourceLine" id="cb23-22" data-line-number="22">}</a></code></pre></div>
<ul>
<li>Léquivalent en Kotlin</li>
</ul>
<div class="sourceCode" id="cb24"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb24-1" data-line-number="1"><span class="kw">data</span> <span class="kw">class</span> Person(<span class="kw">var</span> <span class="va">name</span>: <span class="dt">String</span>, <span class="kw">var</span> <span class="va">age</span>: <span class="dt">Int</span>)</a></code></pre></div>
<ul>
<li>\o/ sympa… mais contraintes :
<ul>
<li>Ne peut pas être <code>abstract</code>, <code>open</code>, <code>sealed</code>, <code>inner</code></li>
<li>Ctor principal doit avoir au moins un paramètre</li>
<li>Les paramètres doivent tous être marqués <code>val</code> ou <code>var</code></li>
<li><code>equals()</code>, <code>hashCode()</code>, <code>toString()</code> non générée si présentes explicitement</li>
</ul></li>
<li>Instanciation : pas besoin de <code>new</code></li>
</ul>
<div class="sourceCode" id="cb25"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb25-1" data-line-number="1"><span class="kw">val</span> <span class="va">moi</span> = Person(<span class="st">&quot;Laurent Provot&quot;</span>, <span class="dv">27</span>)</a></code></pre></div>
<h2 id="visibilités">Visibilités</h2>
<table>
<colgroup>
<col style="width: 14%" />
<col style="width: 41%" />
<col style="width: 44%" />
</colgroup>
<thead>
<tr class="header">
<th>Modifieur</th>
<th>Package</th>
<th>Classe</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>public</code></td>
<td>partout</td>
<td>à tout ceux qui voient la classe</td>
</tr>
<tr class="even">
<td><code>private</code></td>
<td>au sein du fichier contenant la déclaration</td>
<td>au sein de la classe uniquement</td>
</tr>
<tr class="odd">
<td><code>internal</code></td>
<td>dans le même module</td>
<td>dans le même module à qui voit la classe</td>
</tr>
<tr class="even">
<td><code>protected</code></td>
<td></td>
<td>comme <code>private</code> + dans les classes dérivées</td>
</tr>
</tbody>
</table>
<ul>
<li>module : ensemble de fichiers Kotlin compilés ensemble (pour Android = Gradle source set)</li>
</ul>
<h2 id="constructeur-ctor">Constructeur (Ctor)</h2>
<ul>
<li>Constructeur principal</li>
<li>On ne peut pas spécifier de code tout de suite</li>
</ul>
<div class="sourceCode" id="cb26"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb26-1" data-line-number="1"><span class="kw">class</span> Person <span class="kw">constructor</span>(<span class="va">firstName</span>: <span class="dt">String</span>) {…}</a>
<a class="sourceLine" id="cb26-2" data-line-number="2"><span class="kw">class</span> Person(<span class="va">firstName</span>: <span class="dt">String</span>) {…}</a></code></pre></div>
<ul>
<li>Bloc dinitialisation</li>
<li>On peut utiliser les paramètres du ctor principal dans les blocs dinitialisation et les initialisations dattributs</li>
<li>Initialisations effectuées dans lordre declaré</li>
</ul>
<div class="sourceCode" id="cb27"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb27-1" data-line-number="1"><span class="kw">class</span> Person(<span class="va">name</span>: <span class="dt">String</span>) {</a>
<a class="sourceLine" id="cb27-2" data-line-number="2"> <span class="kw">val</span> <span class="va">nameUpper</span> = name.toUpperCase();</a>
<a class="sourceLine" id="cb27-3" data-line-number="3"></a>
<a class="sourceLine" id="cb27-4" data-line-number="4"> init {</a>
<a class="sourceLine" id="cb27-5" data-line-number="5"> println(<span class="st">&quot;My name is: $name&quot;</span>);</a>
<a class="sourceLine" id="cb27-6" data-line-number="6"> }</a>
<a class="sourceLine" id="cb27-7" data-line-number="7">}</a></code></pre></div>
<ul>
<li>Pour initialisation de propriétés</li>
</ul>
<div class="sourceCode" id="cb28"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb28-1" data-line-number="1"><span class="kw">class</span> Person(<span class="kw">val</span> <span class="va">firstName</span>: <span class="dt">String</span>, <span class="kw">var</span> <span class="va">age</span>: <span class="dt">Int</span>) { … }</a></code></pre></div>
<ul>
<li>Si annotations ou modificateur (visibilité, …)</li>
</ul>
<div class="sourceCode" id="cb29"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb29-1" data-line-number="1"><span class="kw">class</span> Person <span class="kw">private</span> <span class="kw">constructor</span>(<span class="kw">val</span> <span class="va">firstName</span>: <span class="dt">String</span>) { … }</a>
<a class="sourceLine" id="cb29-2" data-line-number="2"><span class="kw">class</span> Person @Inject <span class="kw">constructor</span>(<span class="kw">val</span> <span class="va">firstName</span>: <span class="dt">String</span>) { … }</a></code></pre></div>
<ul>
<li>Ctor secondaires</li>
</ul>
<div class="sourceCode" id="cb30"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb30-1" data-line-number="1"><span class="kw">class</span> Person(<span class="kw">val</span> <span class="va">name</span>: <span class="dt">String</span>) {</a>
<a class="sourceLine" id="cb30-2" data-line-number="2"> <span class="kw">constructor</span>(name: Streing, parent: Person) : <span class="kw">this</span>(name) {</a>
<a class="sourceLine" id="cb30-3" data-line-number="3"> parent.children.add(<span class="kw">this</span>)</a>
<a class="sourceLine" id="cb30-4" data-line-number="4"> }</a>
<a class="sourceLine" id="cb30-5" data-line-number="5">}</a></code></pre></div>
<ul>
<li>Délégation au contructeur principal obligatoire (implicite sinon)</li>
<li>Tous les blocs dinitialisation sont appelés</li>
<li>Ctor par défaut si non précisé ou si tous les paramètres ont des valeurs par défaut</li>
</ul>
<h2 id="propriétés-getter-setter">Propriétés &amp; getter / setter</h2>
<ul>
<li>Attribut déclaré avec <code>val</code> = propriété en lecture seule</li>
<li>Attribut déclaré avec <code>var</code> = propriété en lecture / écriture</li>
</ul>
<div class="sourceCode" id="cb31"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb31-1" data-line-number="1"><span class="kw">class</span> Person {</a>
<a class="sourceLine" id="cb31-2" data-line-number="2"> <span class="kw">var</span> <span class="va">name</span> = <span class="st">&quot;John Doe&quot;</span>;</a>
<a class="sourceLine" id="cb31-3" data-line-number="3">}</a>
<a class="sourceLine" id="cb31-4" data-line-number="4">john = Person();</a></code></pre></div>
<ul>
<li>Accès : <code>john.name</code> (utilisation du getter)</li>
<li>Modification : <code>john.name = &quot;johnny&quot;</code> (utilisation du setter)</li>
<li>Syntaxe complète</li>
</ul>
<div class="sourceCode" id="cb32"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb32-1" data-line-number="1"><span class="kw">var</span> &lt;<span class="va">propertyName</span>&gt;[: PropertyType] [= &lt;initializer&gt;]</a>
<a class="sourceLine" id="cb32-2" data-line-number="2"> [&lt;getter&gt;] </a>
<a class="sourceLine" id="cb32-3" data-line-number="3"> [&lt;setter&gt;]</a></code></pre></div>
<ul>
<li>Propriété personnalisée : accès à lattribut avec <code>field</code></li>
</ul>
<div class="sourceCode" id="cb33"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb33-1" data-line-number="1"><span class="kw">var</span> <span class="va">speed</span>: <span class="kw">Int</span></a>
<a class="sourceLine" id="cb33-2" data-line-number="2"> <span class="kw">get</span>() = field * <span class="dv">100</span>; </a>
<a class="sourceLine" id="cb33-3" data-line-number="3"> <span class="kw">set</span>(value) {</a>
<a class="sourceLine" id="cb33-4" data-line-number="4"> <span class="cf">if</span> (value &gt;= <span class="dv">0</span>) field = value;</a>
<a class="sourceLine" id="cb33-5" data-line-number="5"> }</a></code></pre></div>
<ul>
<li>Attribut (<em>backing field</em>) fourni seulement si nécessaire</li>
</ul>
<div class="sourceCode" id="cb34"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb34-1" data-line-number="1"><span class="kw">val</span> <span class="va">isEmpty</span>: <span class="kw">Boolean</span></a>
<a class="sourceLine" id="cb34-2" data-line-number="2"> <span class="kw">get</span>() = <span class="kw">this</span>.size == <span class="dv">0</span></a></code></pre></div>
<ul>
<li>Changement de visibilité ou ajout dannotation en conservant limplémentation par défaut</li>
</ul>
<div class="sourceCode" id="cb35"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb35-1" data-line-number="1"><span class="kw">var</span> <span class="va">devOnly</span>: <span class="kw">String</span></a>
<a class="sourceLine" id="cb35-2" data-line-number="2"> <span class="at">@NotNull</span> <span class="kw">get</span></a>
<a class="sourceLine" id="cb35-3" data-line-number="3"> <span class="kw">private</span> <span class="kw">set</span></a></code></pre></div>
<h2 id="héritage">Héritage</h2>
<ul>
<li>Hiérarchie basée sur la classe <code>Any</code> (≠ <code>java.lang.Object</code>)</li>
<li>Autorisation excplicite de lhéritage avec <code>open</code> (lopposé de <code>final</code> en Java)</li>
</ul>
<div class="sourceCode" id="cb36"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb36-1" data-line-number="1"><span class="kw">open</span> <span class="kw">class</span> Base(<span class="va">arg</span>: <span class="dt">String</span>)</a>
<a class="sourceLine" id="cb36-2" data-line-number="2"><span class="kw">class</span> Derived(<span class="va">num</span>: <span class="dt">Int</span>) : <span class="dt">Base</span>(<span class="va">arg</span>.<span class="va">toString</span>())</a></code></pre></div>
<ul>
<li>Ctor secondaires : appel obligatoire de <code>super</code> ou délégation à un autre ctor</li>
</ul>
<div class="sourceCode" id="cb37"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb37-1" data-line-number="1"><span class="kw">class</span> Derived : <span class="dt">Base</span> {</a>
<a class="sourceLine" id="cb37-2" data-line-number="2"> <span class="kw">constructor</span>(arg: <span class="kw">String</span>, num: <span class="kw">Int</span>) : <span class="kw">super</span>(arg) {…}</a>
<a class="sourceLine" id="cb37-3" data-line-number="3"> <span class="kw">constructor</span>(arg: <span class="kw">String</span>) : <span class="kw">this</span>(arg, <span class="dv">42</span>)</a>
<a class="sourceLine" id="cb37-4" data-line-number="4">}</a></code></pre></div>
<ul>
<li>Redéfinition de méthode : explicite avec <code>override</code></li>
</ul>
<div class="sourceCode" id="cb38"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb38-1" data-line-number="1"><span class="kw">open</span> <span class="kw">class</span> Base {</a>
<a class="sourceLine" id="cb38-2" data-line-number="2"> <span class="kw">open</span> <span class="kw">fun</span> <span class="fu">fo</span>() {…}</a>
<a class="sourceLine" id="cb38-3" data-line-number="3"> <span class="kw">fun</span> <span class="fu">fc</span>() {…}</a>
<a class="sourceLine" id="cb38-4" data-line-number="4">}</a>
<a class="sourceLine" id="cb38-5" data-line-number="5"><span class="kw">class</span> Derived() : <span class="dt">Base</span>() {</a>
<a class="sourceLine" id="cb38-6" data-line-number="6"> <span class="kw">override</span> <span class="kw">fun</span> <span class="fu">fo</span>() {…}</a>
<a class="sourceLine" id="cb38-7" data-line-number="7">}</a></code></pre></div>
<ul>
<li>Un membre déclaré <code>override</code> est automatiquement <code>open</code>; si non désiré : le marquer <code>final</code></li>
<li>Redéfinition de propriété : pareil que pour les méthodes</li>
<li>On peut redéfinir un <code>val</code> en <code>var</code></li>
<li><code>override</code> peut être utilisé dans le constructeur prinicpal</li>
</ul>
<div class="sourceCode" id="cb39"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb39-1" data-line-number="1"><span class="kw">open</span> <span class="kw">class</span> Base {</a>
<a class="sourceLine" id="cb39-2" data-line-number="2"> <span class="kw">open</span> <span class="kw">val</span> <span class="va">x</span>: <span class="kw">Int</span> = <span class="dv">0</span> </a>
<a class="sourceLine" id="cb39-3" data-line-number="3">}</a>
<a class="sourceLine" id="cb39-4" data-line-number="4"><span class="kw">class</span> Derived : <span class="dt">Base</span>() {</a>
<a class="sourceLine" id="cb39-5" data-line-number="5"> <span class="kw">override</span> <span class="kw">var</span> <span class="va">x</span>: <span class="kw">Int</span> = <span class="dv">42</span></a>
<a class="sourceLine" id="cb39-6" data-line-number="6">}</a>
<a class="sourceLine" id="cb39-7" data-line-number="7"><span class="kw">class</span> AnotherDerived(<span class="kw">override</span> <span class="kw">val</span> <span class="va">x</span>: <span class="dt">Int</span>) : <span class="dt">Base</span>()</a></code></pre></div>
<ul>
<li>Comme en Java, le code de la classe dérivée peut appeler des méthodes/propriétés de sa classe de base grâce au mot clé <code>super</code></li>
<li>Classe et méthode abstraite : déclarées avec le mot clé <code>abstract</code></li>
<li><code>abstract</code> implique <code>open</code></li>
</ul>
<h2 id="interfaces">Interfaces</h2>
<ul>
<li>Comme en Java</li>
<li>Une interface peut contenir des propriétés mais elles seront soit abstraites, soit <code>val</code> et sans <em>backing field</em></li>
</ul>
<div class="sourceCode" id="cb40"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb40-1" data-line-number="1"><span class="kw">interface</span> Named {</a>
<a class="sourceLine" id="cb40-2" data-line-number="2"> <span class="kw">val</span> <span class="va">name</span>: <span class="kw">String</span></a>
<a class="sourceLine" id="cb40-3" data-line-number="3">}</a>
<a class="sourceLine" id="cb40-4" data-line-number="4"></a>
<a class="sourceLine" id="cb40-5" data-line-number="5"><span class="kw">interface</span> FullNamed : <span class="dt">Named</span> {</a>
<a class="sourceLine" id="cb40-6" data-line-number="6"> <span class="kw">val</span> <span class="va">firstName</span>: <span class="kw">String</span></a>
<a class="sourceLine" id="cb40-7" data-line-number="7"> <span class="kw">val</span> <span class="va">lastName</span>: <span class="kw">String</span></a>
<a class="sourceLine" id="cb40-8" data-line-number="8"> </a>
<a class="sourceLine" id="cb40-9" data-line-number="9"> <span class="kw">override</span> <span class="kw">val</span> <span class="va">name</span>: <span class="kw">String</span> <span class="kw">get</span>() = <span class="st">&quot;$firstName $lastName&quot;</span></a>
<a class="sourceLine" id="cb40-10" data-line-number="10">}</a>
<a class="sourceLine" id="cb40-11" data-line-number="11"></a>
<a class="sourceLine" id="cb40-12" data-line-number="12"><span class="kw">data</span> <span class="kw">class</span> Person(</a>
<a class="sourceLine" id="cb40-13" data-line-number="13"> <span class="kw">override</span> <span class="kw">val</span> <span class="va">firstName</span>: <span class="dt">String</span>,</a>
<a class="sourceLine" id="cb40-14" data-line-number="14"> <span class="kw">override</span> <span class="kw">val</span> <span class="va">lastName</span>: <span class="dt">String</span></a>
<a class="sourceLine" id="cb40-15" data-line-number="15">) : <span class="dt">FullNamed</span></a></code></pre></div>
<ul>
<li>Désambiguïsation grâce à <code>super&lt;&gt;</code> si implémentation dans linterface</li>
</ul>
<div class="sourceCode" id="cb41"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb41-1" data-line-number="1"><span class="kw">interface</span> A {</a>
<a class="sourceLine" id="cb41-2" data-line-number="2"> <span class="kw">fun</span> <span class="fu">foo</span>() { print(<span class="st">&quot;A&quot;</span>) }</a>
<a class="sourceLine" id="cb41-3" data-line-number="3">}</a>
<a class="sourceLine" id="cb41-4" data-line-number="4"></a>
<a class="sourceLine" id="cb41-5" data-line-number="5"><span class="kw">interface</span> B {</a>
<a class="sourceLine" id="cb41-6" data-line-number="6"> <span class="kw">fun</span> <span class="fu">foo</span>() { print(<span class="st">&quot;B&quot;</span>) }</a>
<a class="sourceLine" id="cb41-7" data-line-number="7">}</a>
<a class="sourceLine" id="cb41-8" data-line-number="8"></a>
<a class="sourceLine" id="cb41-9" data-line-number="9"><span class="kw">class</span> C : <span class="dt">A</span>, <span class="dt">B</span> {</a>
<a class="sourceLine" id="cb41-10" data-line-number="10"> <span class="kw">override</span> <span class="kw">fun</span> <span class="fu">foo</span>() {</a>
<a class="sourceLine" id="cb41-11" data-line-number="11"> <span class="kw">super</span>&lt;A&gt;.foo()</a>
<a class="sourceLine" id="cb41-12" data-line-number="12"> <span class="kw">super</span>&lt;B&gt;.foo()</a>
<a class="sourceLine" id="cb41-13" data-line-number="13"> }</a>
<a class="sourceLine" id="cb41-14" data-line-number="14">}</a></code></pre></div>
<h2 id="classes-de-données">Classes de données</h2>
<div class="sourceCode" id="cb42"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb42-1" data-line-number="1"><span class="kw">data</span> <span class="kw">class</span> User(<span class="kw">val</span> <span class="va">name</span>: <span class="dt">String</span>, <span class="kw">val</span> <span class="va">age</span>: <span class="dt">Int</span>)</a></code></pre></div>
<ul>
<li>En plus des propriétés, <code>toString()</code> et <code>equals()</code> / <code>hashCode()</code>
<ul>
<li><code>copy()</code></li>
<li><code>component1()</code>, …, <code>componentN()</code> functions</li>
</ul></li>
<li><p>Méthode <code>copy</code> :</p>
<div class="sourceCode" id="cb43"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb43-1" data-line-number="1"><span class="kw">fun</span> <span class="fu">copy</span>(<span class="va">name</span>: <span class="dt">String</span> = this.name, <span class="va">age</span>: <span class="dt">Int</span> = this.age) = User(name, age)</a>
<a class="sourceLine" id="cb43-2" data-line-number="2"></a>
<a class="sourceLine" id="cb43-3" data-line-number="3"><span class="kw">val</span> <span class="va">john</span> = User(name = <span class="st">&quot;John&quot;</span>, age = <span class="dv">42</span>)</a>
<a class="sourceLine" id="cb43-4" data-line-number="4"><span class="kw">val</span> <span class="va">youngJohn</span> = john.copy(age = <span class="dv">22</span>)</a></code></pre></div></li>
<li>Méthodes <code>component</code> : déstructuration de la classe</li>
<li>Pour chaque propriété du ctor principal, dans lordre de déclaration</li>
<li><p>Underscore possible si paramètre non utilisé</p>
<div class="sourceCode" id="cb44"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb44-1" data-line-number="1">println(john.component1()) <span class="co">// affiche &quot;John&quot;</span></a>
<a class="sourceLine" id="cb44-2" data-line-number="2"><span class="kw">val</span> (<span class="va">name</span>, age) = john</a>
<a class="sourceLine" id="cb44-3" data-line-number="3">println(<span class="st">&quot;$name, $age years old&quot;</span>) <span class="co">// affiche &quot;John, 42 years old&quot;</span></a></code></pre></div></li>
<li><p>Sympa pour les retours de fonctions, Map, itérations avec index</p></li>
</ul>
<h2 id="object-companion-object"><code>object</code> &amp; Companion object</h2>
<ul>
<li>Généralisation des classes anonymes de Java</li>
<li>Expression objet = création dune instance locale avec certains comportements</li>
</ul>
<div class="sourceCode" id="cb45"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb45-1" data-line-number="1">button.addMouseListener(<span class="kw">object</span> : <span class="dt">MouseAdapter</span>() {</a>
<a class="sourceLine" id="cb45-2" data-line-number="2"> <span class="kw">override</span> <span class="kw">fun</span> <span class="fu">mouseClicked</span>(<span class="va">e</span>: <span class="dt">MouseEvent</span>) { … }</a>
<a class="sourceLine" id="cb45-3" data-line-number="3"> <span class="kw">override</span> <span class="kw">fun</span> <span class="fu">mouseEntered</span>(<span class="va">e</span>: <span class="dt">MouseEvent</span>) { … }</a>
<a class="sourceLine" id="cb45-4" data-line-number="4">})</a></code></pre></div>
<ul>
<li>Création dobjet sans supertype non trivial</li>
</ul>
<div class="sourceCode" id="cb46"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb46-1" data-line-number="1"><span class="kw">fun</span> <span class="fu">foo</span>() {</a>
<a class="sourceLine" id="cb46-2" data-line-number="2"> <span class="kw">val</span> <span class="va">local</span> = <span class="kw">object</span> {</a>
<a class="sourceLine" id="cb46-3" data-line-number="3"> <span class="kw">var</span> <span class="va">x</span>: <span class="kw">Int</span> = <span class="dv">0</span></a>
<a class="sourceLine" id="cb46-4" data-line-number="4"> <span class="kw">var</span> <span class="va">y</span>: <span class="kw">Int</span> = <span class="dv">0</span></a>
<a class="sourceLine" id="cb46-5" data-line-number="5"> }</a>
<a class="sourceLine" id="cb46-6" data-line-number="6"> print(local.x + local.y)</a>
<a class="sourceLine" id="cb46-7" data-line-number="7"> print(local::<span class="kw">class</span>.simpleName) // affiche null</a>
<a class="sourceLine" id="cb46-8" data-line-number="8">}</a></code></pre></div>
<ul>
<li><code>object</code> comme valeur de retour</li>
</ul>
<div class="sourceCode" id="cb47"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb47-1" data-line-number="1"><span class="kw">class</span> C {</a>
<a class="sourceLine" id="cb47-2" data-line-number="2"> <span class="co">// Private function : the return type is the anonymous object type</span></a>
<a class="sourceLine" id="cb47-3" data-line-number="3"> <span class="kw">private</span> <span class="kw">fun</span> <span class="fu">foo</span>() = <span class="kw">object</span> { <span class="kw">val</span> <span class="va">x</span>: <span class="kw">String</span> = <span class="st">&quot;x&quot;</span>}</a>
<a class="sourceLine" id="cb47-4" data-line-number="4"></a>
<a class="sourceLine" id="cb47-5" data-line-number="5"> <span class="co">// Public function : so the return type is Any</span></a>
<a class="sourceLine" id="cb47-6" data-line-number="6"> <span class="kw">fun</span> <span class="fu">publicFoo</span>() = <span class="kw">object</span> { <span class="kw">val</span> <span class="va">x</span>: <span class="kw">String</span> = <span class="st">&quot;x&quot;</span> }</a>
<a class="sourceLine" id="cb47-7" data-line-number="7"></a>
<a class="sourceLine" id="cb47-8" data-line-number="8"> <span class="kw">fun</span> <span class="fu">bar</span>() {</a>
<a class="sourceLine" id="cb47-9" data-line-number="9"> <span class="kw">val</span> <span class="va">x1</span> = foo().x <span class="co">// OK</span></a>
<a class="sourceLine" id="cb47-10" data-line-number="10"> <span class="kw">val</span> <span class="va">x2</span> = publicFoo().x <span class="co">// ERROR: Unresolved reference &#39;x&#39;</span></a>
<a class="sourceLine" id="cb47-11" data-line-number="11"> }</a>
<a class="sourceLine" id="cb47-12" data-line-number="12">}</a></code></pre></div>
<ul>
<li>Déclaration dobjet = singletons</li>
<li>Initialisation thread-safe</li>
</ul>
<div class="sourceCode" id="cb48"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb48-1" data-line-number="1"><span class="kw">object</span> DatabaseManager { </a>
<a class="sourceLine" id="cb48-2" data-line-number="2"> <span class="kw">fun</span> <span class="fu">connect</span>(<span class="va">conn</span>: <span class="dt">Connector</span>) { … }</a>
<a class="sourceLine" id="cb48-3" data-line-number="3"> <span class="kw">fun</span> <span class="fu">fetchData</span>() : <span class="dt">Data</span> { … }</a>
<a class="sourceLine" id="cb48-4" data-line-number="4">}</a></code></pre></div>
<ul>
<li>Ne peut pas être du côté droit dune affectation</li>
<li>Ne peut pas être déclaré local</li>
<li>Déclaration dans une classe possible avec le mot clé <code>companion</code></li>
</ul>
<div class="sourceCode" id="cb49"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb49-1" data-line-number="1"><span class="kw">class</span> MyClass {</a>
<a class="sourceLine" id="cb49-2" data-line-number="2"> <span class="kw">companion</span> <span class="kw">object</span> Factory {</a>
<a class="sourceLine" id="cb49-3" data-line-number="3"> <span class="kw">fun</span> <span class="fu">create</span>(): <span class="dt">MyClass</span> = MyClass()</a>
<a class="sourceLine" id="cb49-4" data-line-number="4"> }</a>
<a class="sourceLine" id="cb49-5" data-line-number="5">}</a>
<a class="sourceLine" id="cb49-6" data-line-number="6"></a>
<a class="sourceLine" id="cb49-7" data-line-number="7"><span class="kw">val</span> <span class="va">instance</span> = MyClass.create()</a></code></pre></div>
<ul>
<li>Utilisation à la <code>static</code> de Java</li>
<li>Mais attention <code>Factory</code> implique une instance dobjet</li>
<li>Utilisation de <code>@JvmStatic</code> si on veut que cela génère des membres <code>static</code> dans le bytecode Java</li>
<li>Les expressions objet sont exécutées <em>immédiatement</em>, les déclarations objet sont initialisées de manière <em>paresseuse</em> et les <code>companion object</code> au moment du chargement de leur classe dattachement</li>
</ul>
<h2 id="retour-sur-les-fonctions">Retour sur les fonctions</h2>
<ul>
<li>Les fonctions sont des variables comme les autres</li>
<li>Elles ont un type :
<ul>
<li><code>(A, B) -&gt; C</code> : une fonction qui prend 2 paramètres le premier de type <code>A</code>, le second de type <code>B</code> et retoune un <code>C</code></li>
<li><code>() -&gt; A</code> : pas de paramètre en entrée</li>
<li><code>(A) -&gt; Unit</code> : pas de valeur de retour</li>
<li><code>A.(B) -&gt; C</code> : fonction qui peut être appelée sur un objet de type <code>A</code>, prend un paramètre de type <code>B</code> et retourne une valeur de type <code>C</code></li>
</ul></li>
<li>Création concise grâce aux lambda</li>
</ul>
<div class="sourceCode" id="cb50"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb50-1" data-line-number="1"><span class="kw">val</span> <span class="va">square</span> = { num: <span class="kw">Int</span> -&gt; num * num }; <span class="co">// (Int) -&gt; Int</span></a>
<a class="sourceLine" id="cb50-2" data-line-number="2"><span class="kw">val</span> <span class="va">more</span> : (<span class="kw">String</span>, <span class="kw">Int</span>) -&gt; <span class="kw">String</span> = { str, num -&gt; str + num }</a>
<a class="sourceLine" id="cb50-3" data-line-number="3"><span class="kw">val</span> <span class="va">noReturn</span> : <span class="kw">Int</span> -&gt; <span class="kw">Unit</span> = { num -&gt; println(num) }</a></code></pre></div>
<ul>
<li>Pour les lambdas qui ne prennent quun paramètre : <code>it</code></li>
</ul>
<div class="sourceCode" id="cb51"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb51-1" data-line-number="1"><span class="kw">val</span> <span class="va">noReturn</span> : <span class="kw">Int</span> -&gt; <span class="kw">Unit</span> = { println(it) }</a>
<a class="sourceLine" id="cb51-2" data-line-number="2"><span class="kw">val</span> <span class="va">concatInt</span> : <span class="kw">String</span>.(<span class="kw">Int</span>) -&gt; <span class="kw">String</span> = { <span class="kw">this</span> + it }</a></code></pre></div>
<ul>
<li>Utilisation</li>
</ul>
<div class="sourceCode" id="cb52"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb52-1" data-line-number="1"><span class="kw">fun</span> &lt;<span class="dt">T</span>, <span class="dt">R</span>&gt; <span class="fu">Collection</span>&lt;<span class="dt">T</span>&gt;.<span class="fu">fold</span>(</a>
<a class="sourceLine" id="cb52-2" data-line-number="2"> <span class="va">initial</span>: <span class="dt">R</span>, </a>
<a class="sourceLine" id="cb52-3" data-line-number="3"> <span class="va">combine</span>: (<span class="dt">acc</span>: <span class="dt">R</span>, <span class="dt">nextElement</span>: <span class="dt">T</span>) -&gt; <span class="dt">R</span></a>
<a class="sourceLine" id="cb52-4" data-line-number="4">): <span class="dt">R</span> {</a>
<a class="sourceLine" id="cb52-5" data-line-number="5"> <span class="kw">var</span> <span class="va">accumulator</span>: R = initial</a>
<a class="sourceLine" id="cb52-6" data-line-number="6"> <span class="cf">for</span> (element: T <span class="kw">in</span> <span class="kw">this</span>) {</a>
<a class="sourceLine" id="cb52-7" data-line-number="7"> accumulator = combine(accumulator, element)</a>
<a class="sourceLine" id="cb52-8" data-line-number="8"> }</a>
<a class="sourceLine" id="cb52-9" data-line-number="9"> <span class="kw">return</span> accumulator</a>
<a class="sourceLine" id="cb52-10" data-line-number="10">}</a>
<a class="sourceLine" id="cb52-11" data-line-number="11"></a>
<a class="sourceLine" id="cb52-12" data-line-number="12"><span class="kw">val</span> <span class="va">items</span> = listOf(<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span>)</a>
<a class="sourceLine" id="cb52-13" data-line-number="13">items.(<span class="dv">0</span>, {acc, i -&gt; acc + i}) <span class="co">// 15</span></a>
<a class="sourceLine" id="cb52-14" data-line-number="14">items.(<span class="st">&quot;Elts :&quot;</span>, {res, i -&gt; res + <span class="st">&quot; &quot;</span> + i}) <span class="co">// &quot;Elts : 1 2 3 4 5&quot;</span></a>
<a class="sourceLine" id="cb52-15" data-line-number="15">items.(<span class="dv">1</span>, <span class="kw">Int</span>::times) <span class="co">// 120</span></a></code></pre></div>
<ul>
<li>Une fonction de type <code>A.(B) -&gt; C</code> peut être utilisée en lieu et place de <code>(A, B) -&gt; C</code> et vice versa</li>
<li>Lorsque le dernier paramètre dune fonction est une fonction, si on passe un lambda on peut la sortir des parenthèses</li>
</ul>
<div class="sourceCode" id="cb53"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb53-1" data-line-number="1">items.fold(<span class="dv">0</span>) {sum, i -&gt; sum + i}</a></code></pre></div>
<ul>
<li>Fonctions dextension</li>
<li>Possible dajouter des fonctions à une classe après coup</li>
<li>Toutes les instances peuvent en profiter</li>
</ul>
<div class="sourceCode" id="cb54"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb54-1" data-line-number="1"><span class="kw">fun</span> <span class="fu">String</span>.<span class="fu">reverse</span>() = StringBuilder(<span class="kw">this</span>).reverse.toString()</a>
<a class="sourceLine" id="cb54-2" data-line-number="2"><span class="st">&quot;That&#39;s cool !&quot;</span>.reverse() <span class="co">// &quot;! looc s&#39;tahT&quot;</span></a></code></pre></div>
<ul>
<li>Fonction infixes : <code>infix</code>
<ul>
<li>Fonction membre ou fonction dextension</li>
<li>Un seul paramètre</li>
<li>Pas de <code>vararg</code> ou de paramètre par défaut</li>
</ul></li>
</ul>
<div class="sourceCode" id="cb55"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb55-1" data-line-number="1"><span class="kw">infix</span> <span class="kw">fun</span> <span class="fu">String</span>.<span class="kw">open</span>(<span class="va">rights</span>: <span class="dt">Acces</span>): <span class="dt">File</span> { … }</a>
<a class="sourceLine" id="cb55-2" data-line-number="2"></a>
<a class="sourceLine" id="cb55-3" data-line-number="3"><span class="st">&quot;/home/provot/lecture&quot;</span> <span class="kw">open</span> Access.WRITE</a>
<a class="sourceLine" id="cb55-4" data-line-number="4"><span class="co">// équivalent à</span></a>
<a class="sourceLine" id="cb55-5" data-line-number="5"><span class="st">&quot;/home/provot/lecture&quot;</span>.open(Access.WRITE)</a></code></pre></div>
<h2 id="surcharge-dopérateur">Surcharge dopérateur</h2>
<ul>
<li>Il est possible de surcharger les opérateurs</li>
<li>On redéfinit des méthodes spécifiques de la classe</li>
<li>Elles sont marquées <code>operator</code></li>
<li>+, -, *, /, %, ..
<ul>
<li><code>a + b</code> équivalent à <code>a.plus(b)</code></li>
<li><code>a..b</code> équivalent à <code>a.rangeTo(b)</code></li>
</ul></li>
<li><code>in</code>, <code>!in</code>
<ul>
<li><code>a.contains(b)</code></li>
</ul></li>
<li>Accès indexé <code>[]</code>
<ul>
<li><code>a[i]</code> équivalent à <code>a.get(i)</code></li>
<li><code>a[i] = b</code> équivalent à <code>a.set(i, b)</code></li>
</ul></li>
<li>Appel de méthode
<ul>
<li><code>a(i, j)</code> équivalent à <code>a.invoke(i, j)</code></li>
</ul></li>
<li>a == b
<ul>
<li><code>a?.equals(b) ?: (b === null)</code></li>
</ul></li>
<li>a &gt; b, a &lt; b, a &gt;= b, a &lt;= b
<ul>
<li>obtenus à partir de <code>a.compareTo(b)</code></li>
</ul></li>
</ul>
<h2 id="documentation">Documentation</h2>
<ul>
<li>KDoc + génération avec Dokka</li>
<li>Comme la javadoc</li>
<li>Tags : <code>@param</code>, <code>@return</code>, <code>@constructor</code>, <code>@receiver</code>, <code>@property</code>, <code>@throws</code>, <code>@exception</code>, <code>@sample</code>, <code>@see</code>, <code>@author</code>, <code>@since</code> et <code>@suppress</code></li>
</ul>
<div class="sourceCode" id="cb56"><pre class="sourceCode kotlin"><code class="sourceCode kotlin"><a class="sourceLine" id="cb56-1" data-line-number="1"><span class="co">/**</span></a>
<a class="sourceLine" id="cb56-2" data-line-number="2"><span class="co"> * A group of *members*.</span></a>
<a class="sourceLine" id="cb56-3" data-line-number="3"><span class="co"> *</span></a>
<a class="sourceLine" id="cb56-4" data-line-number="4"><span class="co"> * This class has no useful logic; it&#39;s just a documentation example.</span></a>
<a class="sourceLine" id="cb56-5" data-line-number="5"><span class="co"> *</span></a>
<a class="sourceLine" id="cb56-6" data-line-number="6"><span class="co"> * @param T the type of a member in this group.</span></a>
<a class="sourceLine" id="cb56-7" data-line-number="7"><span class="co"> * @property name the name of this group.</span></a>
<a class="sourceLine" id="cb56-8" data-line-number="8"><span class="co"> * @constructor Creates an empty group.</span></a>
<a class="sourceLine" id="cb56-9" data-line-number="9"><span class="co"> */</span></a>
<a class="sourceLine" id="cb56-10" data-line-number="10"><span class="kw">class</span> Group&lt;<span class="dt">T</span>&gt;(<span class="kw">val</span> <span class="va">name</span>: <span class="dt">String</span>) {</a>
<a class="sourceLine" id="cb56-11" data-line-number="11"> <span class="co">/**</span></a>
<a class="sourceLine" id="cb56-12" data-line-number="12"><span class="co"> * Adds a [member] to this group.</span></a>
<a class="sourceLine" id="cb56-13" data-line-number="13"><span class="co"> * @return the new size of the group.</span></a>
<a class="sourceLine" id="cb56-14" data-line-number="14"><span class="co"> */</span></a>
<a class="sourceLine" id="cb56-15" data-line-number="15"> <span class="kw">fun</span> <span class="fu">add</span>(<span class="va">member</span>: <span class="dt">T</span>): <span class="dt">Int</span> { ... }</a>
<a class="sourceLine" id="cb56-16" data-line-number="16">}</a></code></pre></div>
</article>
</body>
</html>