De java à swift en 2 temps trois mouvements

Post on 23-Jan-2018

369 views 0 download

Transcript of De java à swift en 2 temps trois mouvements

DE JAVA À SWIFT  EN 2 TEMPS  

TROIS MOUVEMENTS

3 novembre 2016 ( )Didier Plaindoux @dplaindoux

Computer scientist Freelance

λ

Développement lancé en 2010 par Chris Lattner

HISTORIQUE DE SWIFT

v1.0: Dévoilé durant la WWDC en 2014v2.0: Ouverture du compilateur en 2015v3.0: Publication en septembre 2016

DÉVELOPPER AVEC SWIFT

XCode

CLion

Vi, Emacs

EXÉCUTER SWIFT

iOS, OSX

Version 14.04+

(Docker)

IBM Cloud (LinuxOne)

LANGAGE INSPIRÉ PAR ...

Objective-C C#

Orienté Objet

Haskell OCaml

Fonctionnel

Ruby Python

Expressivité

MÉTAMORPHOSE D'UNE CLASSE JAVA

public class Personne { private final String nom; private int age;

public Personne(String nom, int age) { this.nom = nom; this.age = age; }

public void anniversaire() { this.age += 1; } }

SÉPARATEURS

public class Personne { private final String nom private int age

public Personne(String nom, int age) { this.nom = nom this.age = age } public void anniversaire() { this.age += 1 } }

ATTRIBUTS

public class Personne { private let nom:String // Constant private var age:Int // Variable

public Personne(String nom, int age) { this.nom = nom this.age = age }

public void anniversaire() { this.age += 1 } }

PARAMÈTRES

public class Personne { private let nom:String private var age:Int

public Personne(nom:String, age:Int) { this.nom = nom this.age = age }

public void anniversaire() { this.age += 1 } }

INITIALISATION

public class Personne { private let nom:String private var age:Int

public init(nom:String, age:Int) { this.nom = nom this.age = age }

public void anniversaire() { this.age += 1 } }

FONCTION

public class Personne { private let nom:String private var age:Int

public init(nom:String, age:Int) { this.nom = nom this.age = age }

public func anniversaire() -> Void { this.age += 1 } }

FONCTION OU PROCÉDURE

public class Personne { private let nom:String private var age:Int

public init(nom:String, age:Int) { this.nom = nom this.age = age }

public func anniversaire() { this.age += 1 } }

UNE CLASSE SWIFT

public class Personne { private let nom:String private var age:Int

public init(nom:String, age:Int) { self.nom = nom self.age = age }

public func anniversaire() { self.age += 1 } }

SURVOL DU LANGAGE

DONNÉES, TYPES INITIAUX ETC.

Le Fonctionnel

Les Objets

VARIABLES OU CONSTANTES

JAVA SWIFT

int age

final String nom

var age:Int

let nom:String

LES COLLECTIONS

JAVA SWIFT

Arrays.asList("Hello", "World")

Map<String, Integer> m = new HashMap<>(); m.put("A", 10); m.put("B", 20);

["Hello", "World"]

["A":10, "B":20]

Fonctions disponibles map, �atMap, �lter etc.

DONNÉE OPTIONNELLE

JAVA SWIFT

Optional<String> n = Optional.of("A"); Optional<Integer> t = n.map(v -> v.length()); if (t.isPresent()) { // t.get(); }

let n:String? = "A" // ou nil let t:Int? = n?.characters.count if let taille = t { // taille utilisable }

Fonctions disponibles map, �atMap, �lter etc.

Donnée optionnelle "portée" par le typage uniquement. Non structurel !

TUPLES

JAVA

SWIFT

Index ↔ Nom

(42, "John Doe") // (Int, String) (42, "John Doe").1 == "John Doe"

(42, nom:"John Doe") // (Int, String) (42, nom:"John Doe").1 == "John Doe" (42, nom:"John Doe").nom == "John Doe"

STRUCTURES DE CONTRÔLE

Sélection conditionnelle

Garde pour les optionnels

Répétition

if expression { // bloc en cas de succés } else { // bloc optionnel en cas d'échec }

guard let valeur = expression else { // valeur n'est pas définie }

// valeur est définie

let segment = 0..<100 for index in segment { // bloc répété}

Données, Types initiaux etc.

LE FONCTIONNEL

Les Objets

TYPE FONCTIONNEL

JAVA SWIFT

Type aliasing

Function<A,B> Supplier<B> Consumer<A> Predicate<A> ...

(A) -> B () -> B (A) -> () (A) -> Bool ...

typealias Supplier<B> = () -> B

FONCTION

func Nom(Parametres) -> Type Resultat { Corps De La Fonction }

FONCTION :: PARAMÈTRES

func multiplier(a:Int, b:Int) -> Int { return a * b }

En interne les noms des paramètres capturent les valeurs lors de l'appel

multiplier(a:2, b:3)

En externe les noms des paramètres servent de "marques" pour les arguments

Permutation des arguments interdite

FONCTION :: NOM EXTERNE SPÉCIFIQUE

Spéci�cation d'un nom externe di�érent

func multiplier(a:Int, par b:Int) -> Int { return multiplier(a:a, b:b) }

multiplier(a:2, par:3)

FONCTION :: AUCUN NOM EXTERNE

Spéci�cation a�n de ne pas avoir de nom externe

func multiplier( _ a:Int, par b:Int) -> Int { return multiplier(a:a, b:b) }

multiplier(2, par:3)

FONCTION ANONYME :: CLOSURE

JAVA

SWIFT

[Parametres] -> [Corps De La Fonction]

{ [Parametres] -> [Type Retour] in [Corps De La Fonction] } { [Parametres] in [Corps De La Fonction] }

Objet de Première Classe

CLOSURE :: EXEMPLES

let multiplier = { (a:Int, b:Int) -> Int in a * b }

Pas de séléction par nommage des paramètres car inutile !

multiplier(2,3)

CLOSURE :: SYNTHÈSE DE TYPE

let multiplier = { (a:Int,b:Int) in a * b } let multiplier = { (a,b:Int) in a * b } let multiplier = { a,b -> Int in a * b }

// (Int, Int) -> Int

CLOSURE :: SYNTHÈSE DE TYPE

let multiplier = { a,b in a * b }

error ambiguous use of operator '*'

Int ? Float ? Double ? ...

CLOSURE :: SYNTHÈSE DE TYPE !

let multiplier : (Int,Int) -> Int = { a,b in a * b }

Spéci�cation vs. Mise en oeuvre

FONCTION :: ORDRE SUPÉRIEUR

Fonction qui manipule une fonction

func appliquer(_ f:(Int) -> Int, _ a:Int) -> Int { return f(a) }

// appliquer(f,a) ⟶* f(a)

Forme restreinte au type Int → Int !

FONCTION :: GÉNÉRICITÉ

Paramétrisation à la C++, Java, C#

func appliquer<A,B>(_ f:(A) -> B, _ a:A) -> B { return f(a) }

Possibilité de spéci�er des contraintes

func estEgal<A:Equatable>(_ a:A, _ b:A) -> Bool { return a == b }

INCONSISTANCE & PIÈCES MANQUANTES

η-conversion pas généralisable en présence de surcharges équivalentes

Récursivité terminale Non garantie par le compilateur

Compréhension Concept inexistant

{ x in f(x) } ≡? f

Données, Types initiaux etcs.

Le Fonctionnel

LES OBJETS

LES OBJETS

Ecole Scandinave

Simula, C++, Objective-C, Ei�el, Java, C# ... Swift

Abstraction de donnée ↔ Classe ↔ Type

Repose sur un Typage Statique

PARADIGME OBJET

JAVA SWIFT

Interface Protocole

Classe Classe

∅ Structure

Enumération Enumération

PROTOCOLE

Base de connaissancesExtension de Protocoles

PROTOCOLE :: BASE DE CONNAISSANCES

public protocol Monde { func vivants() -> [Personne] func recherche(nom:String) -> Personne? }

PROTOCOLE :: MISE EN OEUVRE

extension Monde { func recherche(nom:String) -> Personne? { return vivants().filter{ p in p.nom == nom }.first } }

Assimilable au "default" des interfaces dans Java 8

Idem pour les classes, structures et enumérations

PROTOCOLE :: GÉNÉRICITÉ

protocol Copiable { associatedtype E func copier<C:Copiable where C.E == E>() -> C // 0_o }

Spéci�cation de Type Membre ≢ Paramétrisation

Spécialisation par le typealias

CLASSE

Etat interneBase de connaissancesHéritage simpleMise en oeuvre de Protocoles

CLASSE :: ETAT INTERNE & INITIALISATION

public class Personne { private let nom:String private var age:Int

public init(nom:String, age:Int) { self.nom = nom self.age = age } }

Pas de mot clé new

Personne(nom:"John Doe", age:42)

CLASSE :: INITIALISATION & OPTIONNEL

Initialisation pouvant retourner nil

public class Personne { private let nom:String private var age:Int

public init?(nom:String, age:Int) { guard age > -1 else { return nil } // if age < 0 { return nil }

self.nom = nom self.age = age } }

let personne:Personne? = Personne(nom:"John Doe", age:-1)

CLASSE :: BASE DE CONNAISSANCES

Méthode d'instance(surchargeable)

Méthode statique(non surchargeable)

Méthode de classe(surchargeables)

class Personne { ⊞ ... func aPourNom() -> String { return self.nom } }

class Personne { ⊞ ... static func new(nom:String) -> Personne {...} }

class Personne { ⊞ ... class func new(nom:String) -> Personne {...} }

CLASSE :: REFERENCE TYPEpublic class Personne { private let nom:String private var age:Int

⊞ public init(nom:String, age:Int) { ... } }

let personne1 = Personne(nom:"John Doe", age:42)let personne2 = personne1

personne1 et personne2 référencent la même donnée en mémoire

STRUCTURE

Etat interneBase de connaissancesMise en oeuvre de Protocoles

STRUCTURE :: INITIALISATION

public struct Personne { let nom:String var age:Int }

Méthode init implicite. Redé�nition possible.

Personne(nom:"John Doe", age:42)

STRUCTURE :: REFERENCE VALUEvar personne1 = Personne(nom:"John Doe", age:42)let personne2 = personne1

personne1.age += 1

// personne1.age == 43 // personne2.age == 42

personne1 et personne2 ne référencent pas la même donnée en mémoire

ENUMÉRATION

Spéci�cation de formesEtat interneBase de connaissancesMise en oeuvre de Protocoles

ENUMÉRATION :: SPÉCIFICATION DE FORMES

public enum StadePersonne { case Enfant, Adolescent, Adulte }

let s : StadePersonne = ... switch s { case StadePersonne.Enfant: // ... case StadePersonne.Adolescent: // ... case StadePersonne.Adulte: // ... }

Le switch/case doit être exhaustif / Véri�é à la compilation

ENUMÉRATION :: SWITCH AVANCÉ

public enum PeutEtre<T> { case QuelqueChose(value:T), Rien

public func get(_ valeurParDefaut:T) -> T { switch self { case .QuelqueChose(let v): return v case _: return valeurParDefaut } } }

Pattern Matching

self ou ... Self

self : Self

public class Personne { private let nom:String private var age:Int

⊞ public init(nom:String) { ... }

public func anniversaire() -> Self { self.age += 1 return self } }

Le type Self dénote le type de l'objet courant à savoir ... self

DÉNOTATION DU TYPE COURANT

JAVA SWIFT

interface Copiable<Self extends Copiable<Self>> { Self copie(); }

protocol Copiable { func copie() -> Self }

"F-Bounded quanti�cation polymorphism"

SELF :: COPIABLE

class Personne : Copiable { private let nom:String private var age:Int

func copie() -> Self { return type(of:self).init(nom:self.nom, age:self.age) }

required init(nom:String, age:Int) { self.nom = nom self.age = 0 } }

required force la dé�nition dans les sous-classes

SELF :: INITIALISATION

class Personne { private let nom:String private var age:Int

required init(nom:String, age:Int) { self.nom = nom self.age = 0 }

class func new(nom:String) -> Self { return self.init(nom:nom, age:0) // self ≡ Personne } }

Cela me rappelle furieusement le new de Perl !

UN TOUR D'HORIZON (TROP) RAPIDE !

Gestion des erreursStructure & MutationNotion de moduleSwift & Android via le NDK (Swift ⇒ C)etc ...

PROSÉLYTISME !

Meetup !

Site o�cielA curated list of awesome iOS ecosystem

MERCI