2015-04-20 28 views
11

Widzę pewne dziwne zachowanie w klasie, którą stworzyłem jakiś czas temu, gdzie wydaje się, że właściwości struktury zmieniają się natychmiast po przekazaniu (skopiowaniu) do metody.Przekazanie ogólnej struktury dla nienazwanego domyślnego parametru powoduje wyświetlenie właściwości śmieci

ja gotuje go do prostego testu, które mogą być uruchamiane na placu zabaw:

struct StructToPass<T> { 
    let x: T 
} 

class MyClass<T> { 
    func createAndPassStructWithValue(value: T) { 
     let structToPass = StructToPass(x: value) 
     println("Before passing to method: \(structToPass.x)") 
     passStruct(structToPass) 
    } 

    func passStruct(_ theStruct: StructToPass<T>? = nil) { 
     println("Inside method: \(theStruct!.x)") 
    } 
} 

let myClass = MyClass<Int>() 
myClass.createAndPassStructWithValue(42) 

patrząc na odpowiednich sprawozdań drukowanych, to pokazuje, że struct jest x nieruchomość zmieniła:

// Before passing to method: 42 
// Inside method: 140734543799888 


Tworzenie struct poza klasą i nazywając passStruct(_:) bezpośrednio powoduje awarię zabaw, podobnie jak pisanie passStruct(_:) jako funkcję:

// Causes playground to crash: 
let aStruct = StructToPass(x: 42) 
myClass.passStruct(aStruct) 

// Also causes playground to crash: 
func passStruct<T>(_ theStruct: StructToPass<T>? = nil) {} 
passStruct(aStruct) 


Zmiana passStruct(_:) metody/funkcji, aby użyć domyślnego zewnętrzną nazwę parametru rozwiązuje problemu, podobnie jak wprowadzenie innego parametru (przed/po parametr domyślny):

// This works: 
func passStruct<T>(theStruct: StructToPass<T>? = nil) { 
    println("Inside function: \(theStruct!.x)") 
} 
passStruct(theStruct: aStruct) 

// This also works: 
func passStruct<T>(_ theStruct: StructToPass<T>? = nil, someOtherParam: Int) { 
    println("Inside function: \(theStruct!.x)") 
} 
passStruct(aStruct, 42) 


Czy to błąd kompilatora? Wydaje się, że kompilatorowi się to nie podoba, gdy ogólna funkcja/metoda z pojedynczym argumentem o wartości domyślnej nie używa zewnętrznej nazwy parametru. To konkretny przypadek, ale myślę, że powinien zadziałać. Jeśli to nie powinno działać, powinno być ostrzeżenie kompilatora.

Odpowiedz

2

Błąd kompilatora 110%. Próbowałem nawet tego z Playground. Wszystko szczęśliwie się kompiluje, dopóki nie chcesz dodać linii, która faktycznie coś robi, np. Wysyłając hasło. W tym wszystkim są różne rzeczy. I nawet to nie:

func passStruct<T>(_ theStruct: StructToPass<T>? = (nil as StructToPass<T>?)) { 
    println("Inside function: \(theStruct!.x)") 
} 

który ja trochę, że może być problem (choć nie powinno być, że miałem gdzie indziej).

Dobrze! Zgłoś to. Z pewnością nie są skończone z lekami generycznymi. W moich eksperymentach odkryłem, że ogólne właściwości klas nie są dozwolone.

static let nilStruct: StructToPass<T>? = nil 

nie kompiluje się, z jednym z komunikatów o błędach "jeszcze nieobslugiwane".

+1

Dzięki za twój wkład. Przesłałem zgłoszenie błędu. – Stuart