Init et DidSet sont dans une même classe

Bonjour,


 


Une petite question concernant l'initialisait d'une classe. Je voudrais que ma note soit comprise entre 0 et 127. J'utilise le code suivant :



var chanel: Int {
didSet {
// From 1 to 16
chanel = min(max(chanel,1),16)
}
}

var name: String = ""

// Init methods
init (noteNumber: Int, chanel: Int, name: String)
{
println("init \(noteNumber) : ")
self.noteNumber = noteNumber
self.name = name
self.chanel = chanel
}

Lors de l'appel à  ma méthode init désigné, je ne passe pas par le DidSet. Il y a-t-il un moyen de forcer cela ou mon contrôle n'est-il pas fait au bon endroit ?


 


D'avance merci de votre aide


 


seb


Mots clés:

Réponses

  • Je n'ai pas très bien compris ton problème. Dans le doute, tu ne peux pas utiliser une variable privée comme ça ? :


     



     


    private var _chanel:Int = 0


        


        var chanel : Int {


            set { _chanel = newValue }


            get { return _chanel }


        }


     


    ça  permet d'accéder en interne à  la variable _chanel dans l'init sans passer par les setters/getters. 

  • iLandesiLandes Membre
    juin 2015 modifié #3

    Peut-être je n'ai pas été claire.


     


    Une note est composé d'un entier (entre 0 et 127), d'un canal (1 à  16) et d'un nom (string). Je souhaite vérifier que ma note soit toujours conforme à  ces contraintes.


     


    Mon code fonctionne sauf que mes contraintes ne sont pas vérifiées au moment de la création. C'est ce qui m'embête...


     


    Voici le code complet que j'ai écrit.



    //: Playground - noun: a place where people can play


    import Foundation


    class Note: Printable {

    // Properties
    var noteNumber: Int {
    didSet {
    // From 0 to 127
    noteNumber = min(max(noteNumber,0), 127)
    }
    }

    var chanel: Int {
    didSet {
    // From 1 to 16
    chanel = min(max(chanel,1),16)
    }
    }

    var name: String

    // Init methods
    init (noteNumber: Int, chanel: Int, name: String)
    {
    println("init \(noteNumber) : ")
    self.noteNumber = noteNumber
    self.name = name
    self.chanel = chanel
    }


    convenience init ()
    {
    self.init (noteNumber: 0, chanel: 1, name: "unknow")
    }

    // Printable
    var description: String
    {
    get {
    return "\(noteNumber) | Chanel = \(chanel) | \(name)"
    }
    }
    }


    var myIncorectNote: Note = Note(noteNumber: 1000, chanel: 45, name: "test")
    println("NOT CORRECT : \(myIncorectNote)")

    var myCorrectNote = Note()
    myCorrectNote.noteNumber = 2000 //2000 is invalid

    println("CORRECT : \(myCorrectNote)")




    La console donne


     


    NOT CORRECT : 1000 | Chanel = 45 | test


    CORRECT : 127 | Chanel = 1 | unknow


  • DrakenDraken Membre
    juin 2015 modifié #4

    Avec ça :



    class Note: Printable {

    private var _note = 0
    private var _chanel = 0

    var noteNumber: Int {
    set { _note = min(max(newValue,0), 127) }
    get { return _note }
    }

    var chanel: Int {
    set { _chanel = min(max(newValue,1),16) }
    get { return _chanel }
    }

    var name = ""

    // Init methods
    init (noteNumber: Int, chanel: Int, name: String)
    {
    println("init \(noteNumber) : ")
    self.noteNumber = noteNumber
    self.name = name
    self.chanel = chanel
    }

    convenience init ()
    {
    self.init (noteNumber: 1000, chanel: 45, name: "test")
    }

    // Printable
    var description: String
    {
    get {
    return "\(noteNumber) | Chanel = \(chanel) | \(name)"
    }
    }
    }


    Le programme affiche :


     



     


    init 1000 : 


     


    127 | Chanel = 16 | test



     

    Objectif atteint ..  <3 </div>
    A vrai dire je n'ai jamais utilisé didset. Il me semble plus logique de contrôler la valeur de la donnée avec son setter, plutôt que de passer par un observateur. Ton problème vient probablement du fait que l'observateur est mis en place à  la fin de l'initialisation de la classe Note, et pas au début.

     

    EDIT : Au fait, ton code



    var name : String

    ne passais pas au compilateur (Xcode 6.3). Normal, tu ne l'initialisais pas !


     


    Je l'ai remplacé par une chaà®ne vide, un truc classique en Swift pour éviter de déclarer des variables optionnelles.



    var name = ""

  • AliGatorAliGator Membre, Modérateur
    Tu devrais faire un failable initializer si tu dois foirer ton constructeur au cas où les valeurs ne sont pas bonnes. ça serait plus logique.


    Et c'est normal que le difSet ne soit pas appelé, il n'est jamais appelé dans le init pour éviter les effets de bord.
  • iLandesiLandes Membre
    juin 2015 modifié #6

    J'aime bien la solution de Draken avec les private var à  l'ancienne mais efficace.


     


    Mais j'aimerai bien aller plus loin avec la méthode d'Ali. L'init en swift ne retourne rien, donc comment le rendre failable quand l'initialisation a échoué ?


     


    J'ai fait ça mais je suis pas fan




    import Foundation


    class Note: Printable {

    private struct Constants {
    static let internationalNotesNames = ["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"]
    static let frenchNotesNames = ["Do","Do#","Ré","Ré#","Mi","Fa","Fa#","Sol","Sol#","La","La#","Si"]
    static let latinNotesNames = ["Do","Do#","Ré","Ré#","Mi","Fa","Fa#","Sol","Sol#","La","La#","Ti"]
    }

    var noteNumber: Int {
    // From 0 to 127
    didSet { noteNumber = min(max(noteNumber,0), 127) }
    }

    var chanel: Int {
    // From 1 to 16
    didSet { chanel = min(max(chanel,1),16) }
    }

    var name: String

    // Init methods
    init? (noteNumber: Int, chanel: Int, name: String)
    {
    if noteNumber == min(max(noteNumber,0), 127) && chanel == min(max(chanel,1),16) {
    self.noteNumber = noteNumber
    self.name = name
    self.chanel = chanel
    } else {
    self.noteNumber = 0
    self.name = name
    self.chanel = 1
    return nil
    }
    }


    convenience init? ()
    {
    self.init (noteNumber: 0, chanel: 1, name: "unknow")
    }

    func noteNameInFormat(noteNameArray: [String]) -> String {
    let name = noteNameArray[noteNumber % 12]
    let octavia = abs(noteNumber / 12) - 2
    return "\(name)\(octavia)"
    }


    // Printable
    var description: String
    {
    get {
    return "\(noteNumber) | \(noteNameInFormat (Constants.internationalNotesNames)) | \(noteNameInFormat (Constants.frenchNotesNames)) | Chanel = \(chanel) | \(name)"
    }
    }



    }

    println("Hello, World!")

    if let myIncorectNote = Note (noteNumber: 1000, chanel: 45, name: "test") {

    println("CORRECT : \(myIncorectNote)")
    }
    else {
    println("NOT CORRECT note")
    }

    var myCorrectNote = Note()
    myCorrectNote!.noteNumber = 2000

    println("CORRECT : \(myCorrectNote)")
  • AliGatorAliGator Membre, Modérateur
    Ca sert à  rien d'affecter des valeurs à  tes propriétés si tu finis par faire un "return nil" dans ton "init?(...)" quand il a foiré puisqu'alors ton objet ne sera pas initialisé, ayant raté son initialisation.
Connectez-vous ou Inscrivez-vous pour répondre.