2015-12-15 14 views
9

Powiedzmy mam ten kod:Czy mogę ograniczyć parametr ogólny, aby * nie * było opcjonalne?

func hello<T>(thing: T) -> String { 
    return "hello \(thing)" 
} 

mogę napisać wersję funkcji hello że nie będzie kompilować czy to przeszły opcjonalny?

let foo = "some" 
let bar: String? = nil 

print(helloNoOptional(foo)) // should compile 
print(helloNoOptional(bar)) // should not compile 

myślę może to wykonalne ze zgodności protokołu lub where klauzuli o T, ale nie mogę myśleć o tym, jak dokładnie to będzie działać.

Powodem, dla którego chcę to zrobić, jest fakt, że mam do czynienia z rzeczywistą funkcją w dotychczasowej bazie kodów, która nie ma rozsądnego zachowania, jeśli thing jest zerowa. Tak więc wolałbym, aby hello nie był wywoływany jako opcjonalny, a nie rozpakowywany w trakcie przywracania thing i próba znalezienia sensownego zachowania błędu.

Aktualizacja:

Możliwym ścieżka ... zdałem sobie sprawę, że Opcjonalnie enum jest zgodny z protokołem NilLiteralConvertible. Więc jeśli uda mi się znaleźć sposób na ograniczenie mojego generycznego do , a nie, jest on zgodny z typem, mogę de facto wykluczyć opcje. Ale ja nie wiem, czy to możliwe, aby zrobić coś jak

<T where !T: NilLiteralConvertible> 
+3

Nie jestem całkiem jasny na temat wymagań. Jaką funkcję może pełnić "dosłownie wszystko, bez żadnych ograniczeń, z wyjątkiem jednego konkretnego wyliczenia o nazwie Opcjonalne?" Opcjonalnie ma trochę magii językowej, ale w przeważającej części jest to tylko rodzaj wyliczeniowy. Podejrzewam, że to, co naprawdę chcesz zrobić, to stworzyć protokół, który możesz dołączyć do typów, które * robisz * akceptujesz, zamiast "tylko opcjonalny". –

+0

"Dosłownie cokolwiek, bez żadnych ograniczeń, z wyjątkiem jednego specyficznego wyliczenia zwanego Opcjonalnie" jest dokładnie tym, czego chcę (a dokładniej, cokolwiek z wyjątkiem "zero"). Zgaduję, że kiedy tak to określasz, nie jest to możliwe bez pewnych zależnych typów, ale chcąc ograniczyć typ, aby trzymać tylko określone wartości, okazuje się dość powszechnym przypadkiem użycia dla mnie. – rogueleaderr

+0

Nie jest jasne, w jaki sposób twoja funkcja może działać na "dowolnej wartości z wyjątkiem zer". Co to robi? zero nie jest naprawdę magiczne w Swift. Jest to prawidłowa wartość ("Opcjonalny.Nie"). To nie jest 0 lub NULL lub coś w tym stylu. Możesz ogólnie pracować z zerą dokładnie tak, jak możesz pracować przy jakiejkolwiek innej wartości wyliczeniowej. Nie jest samo w sobie niebezpieczne jak w innych językach. –

Odpowiedz

5

Najlepszy mogę pomyśleć, to przeciążenie i sprawdzić w czasie wykonywania:

func hello<T>(thing: T) -> String { 
    return "hello \(thing)" 
} 

fun hello<T>(thing: T?) -> String { 
    fatalError("No optionals allowed!") 
} 

hello("swift") // fine 
hello(2)  // fine 
hello(Int("2")) // fatal error 

ale nie wiem o sposób generowania zamiast tego błąd kompilacji.

1

Zmieniano

Można stworzyć fikcyjny protokół (NotOfOptionalType poniżej) i rozciągają się wszystkie rodzaje można oczekiwać do wykorzystania w funkcji generycznych przez ten protokół. Wreszcie użyj prototypu fikcyjnego jako ograniczenia typu dla parametru (ów) w twoich ogólnych funkcjach; opcje nie spełniają tego typu ograniczenia i otrzymasz błąd podczas kompilacji, jeśli zostaną wysłane jako parametry dla tych funkcji.

// dummy protocol 
protocol NotOfOptionalType {} 

extension String : NotOfOptionalType {} 
extension Int : NotOfOptionalType {} 
extension Double : NotOfOptionalType {} 
// ... extend to the types you will use 

func hello<T: NotOfOptionalType > (thing: T) -> String { 
    return "hello \(thing)" 
} 

let foo = "some" 
var bar: String? = nil 

print(hello(foo)) // compiles 
print(hello(bar)) // fails at compile time 
bar = "something" 
print(hello(bar)) // fails at compile time 
print(hello(bar!)) // compiles 
+0

Podoba mi się ten pomysł, ale Po prostu próbowałem go i hello (bar) kompiluje się, ale obsada kończy się niepowodzeniem w * czasie wykonywania * nie kompiluje czasu, więc nie przeszkadza programistce 'self.shootFoot()' Miałem nadzieję na. – rogueleaderr

+0

Edytowana odpowiedź: mam nadzieję, że to będzie praca dla Ciebie. – dfri

Powiązane problemy