2015-02-21 15 views
11

Jestem nowy Swift i chciałby zainicjować zmienną składową obiektu, stosując metodę instancji takiego:Wywołanie metody instancji podczas inicjalizacji w Swift

class MyClass { 
    var x: String 
    var y: String 

    func createY() -> String { 
    self.y = self.x + "_test" // this computation could be much more complex 
    } 

    init(x: String) { 
    self.x = x 
    self.y = self.createY() 
    }  
} 

Zasadniczo zamiast inline cały kod inicjalizacji w init metody , Chcę wyodrębnić kod inicjujący y do dedykowanej metody createY i wywołać tę metodę instancji createY w init. Jednak Swift kompilator (Swift 1.2 kompilator w Xcode 6.3 beta) narzeka:

używanie 'ja' na wywołanie metody 'XXX' przed super.init zainicjować Własna

Tutaj 'XXX' jest nazwa metody instancji (createY).

Rozumiem, co kompilator Swift narzeka i jaki potencjalny problem chce rozwiązać. Jednak nie mam pojęcia, jak to naprawić. Jaki powinien być sposób w Swift, aby wywołać inną metodę inicjowania kodu w instancji init?

Obecnie używam następującej sztuczki jak praca wokół, ale nie sądzę, to jest idiomatyczne rozwiązanie tego problemu (i to rozwiązanie wymaga y należy zgłaszać za pomocą var zamiast let co sprawia, że ​​czuję się nieswojo zbyt):

init(x: String) { 
    self.x = x 
    super.init() 
    self.y = createY() 
} 

Każdy komentarz jest mile widziany. Dzięki.

Odpowiedz

9

Konwertuj createY() na funkcję globalną lub klasową, która przyjmuje jako argument x i zwraca wartość y.

Następnie po prostu wywołaj to normalnie ze swojego init.

class MyClass { 
    let x: String 
    let y: String 

    init(x: String) { 
    self.x = x 
    self.y = createY(x) 
    }  
} 
+0

Dzięki za odpowiedź, wydaje się, że wciąż mają zadeklarować " y "używając" var "zamiast" let "nawet jeśli moja zmienna" y "jest niezmienna? – nybon

+0

@nybon Dodałem kod samej klasy, aby pokazać, jak miałem na myśli 'createY()' do użycia. 'let' powinno być w porządku. –

1

Jak odpowiedział here, utwórz funkcję klasy. Dodałem pełny kod.

class MyClass { 
    var x: String 
    var y: String 

    class func createY(x: String) -> String { 
     return x + "_test" // this computation could be much more complex 
    } 

    init(x: String) { 
     self.x = x 
     self.y = MyClass.createY(x) 
    }  
} 
1

myślę Swift sposobem, aby to zrobić, to z komputerowej Properties (https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html)

EDIT

Zamiast wywoływać funkcję zmodyfikować właściwość na planie/dostać, można użyć obliczone właściwości:

class MyClass { 

    var x: String? 
    var y: String? { 
     get { 
      return "\(x!)_test" 
     } 
    } 

    init(x: String!){ 
     self.x = x 
    } 
} 

let myClass = MyClass(x: "string") 
print(myClass.y!) #=> "string_test" 
+0

Możesz poprawić swoją odpowiedź, podając rzeczywisty przykład, a nie tylko link do strony zewnętrznej (która może zniknąć). – zeeMonkeez

+0

Przepraszam, dodałem przykład. – Struki84

+0

Jeśli rozumiem poprawnie, obliczone właściwości wykona obliczenia za każdym razem, gdy dostęp do tej wyliczonej właściwości, czy jest to poprawne? Jeśli obliczenia są kosztowne i potrzebne tylko raz podczas inicjalizacji, jak mam to zrobić? – nybon

0

w Swift 3 Używam tego wzoru,

class MyClass { 
    var x: String? 
    private(set) lazy var y: String? = self.createY() 

    init(x: String){ self.x = x } 

    private func createY() -> String? 
    { 
    return "\(x ?? "nil") test" 
    } 
} 

Tajny sos tutaj jest użycie private(set) lazy. W ten sposób możesz oznaczyć swoją nieruchomość jako var. I lazy opóźni inicjalizację do momentu zakończenia funkcji init. Użycie funkcji private(set) zezwala tylko na funkcje w tej klasie, aby zmodyfikować tę właściwość, w tym słowo kluczowe lazy, ale nie pozwolić, aby publiczne interfejsy zmieniły tę właściwość.Oczywiście, jeśli chcesz, aby twój interfejs zmienił twoją własność, możesz również oznaczyć ją jako internal (domyślnie) lub public. Ale trzeba zostawić to oznaczało lazy var

0

Można zastosować w tym podejściu

klasa MyClass: NSObject {

 let x: String 
     var y: String 

     init(x: String) { 

      self.x = x 
      self.y = self.x + "_test" 
      print(self.x) 
      print(self.y) 
     } 
} 
+0

Dziękuję za odpowiedź, ale jak już wspomniałem powyżej, nie chcę wstawiać "całego kodu inicjującego w metodzie init. – nybon

0
class MyClass { 
     let x: String 
     lazy var y : String = { 
       return x + "_test" 
      }() 
     init(x: String) { 
      self.x = x 
     } 
} 
+1

Niezbyt pomocna bez żadnych dalszych wyjaśnień ;-( – GhostCat