terminy implicit i explicit wymagają przyzwyczajenia, gdy po raz pierwszy je usłyszysz. Kiedy słyszysz je w kategoriach programowania, co dokładnie to dla ciebie znaczy? Czy jedno jest lepsze od drugiego? Tutaj omówimy każdy z tych pomysłów i podamy przykłady z pewnymi korzyściami dla wzorców projektowych, które mogą z nich wynikać.
terminy
w programowaniu, implicit jest często używany w odniesieniu do czegoś, co jest zrobione dla ciebie przez inny kod za kulisami., Explicit jest ręcznym podejściem do osiągnięcia zmiany, którą chcesz mieć, pisząc instrukcje, które mają być wykonane jawnie. W mniejszym obrazie, implicit i explicit są często terminami używanymi do odlewania typów do typu, który chcesz być. W szerszym ujęciu, możesz mówić o konwencji nad konfiguracją, gdzie konwencja jest tym, co domyślnie robi dla Ciebie baza kodu lub framework, a konfiguracja jest po prostu jawnymi ustawieniami.,
istnieją również różnice odpowiedniości lub korzyści dla obu zastosowań w zależności od danego języka programowania i tego, czy język jest typowany statycznie czy dynamicznie. Zależy to również od tego, czy rzeczy można wywnioskować z czasu uruchomienia lub podczas kompilacji. Z powodu tych czynników twierdzenie, że jedna metodologia jest lepsza od drugiej, może być prawdziwe tylko w wąskich kontekstach, ponieważ trzeba wziąć pod uwagę projekt języków programowania i programów, o których mowa.,
przykład jawnego i jawnego odlewania typu W C jest następujący:
int implicit;implicit = 4.5;int explicit;explicit = (int)4.5;
tutaj nazwy zmiennych implicit
I explicit
zostały zdefiniowane jako typu int
. Po podaniu wartości 4.5
wersja implicit przekonwertuje to, co normalnie byłoby typem float lub double na liczbę całkowitą, podczas gdy wersja explicit jawnie rzuciła ją na liczbę całkowitą przy użyciu (int)
jako to, co rzuca Typ.,
języki typowane statycznie
w językach typowanych statycznie, takich jak Rust, zdecydowana większość tworzenia wartości i przypisywania będzie miała wyraźne wymagania dotyczące adnotacji typu, z wyjątkiem sytuacji, w których kompilator może wywnioskować Typ. Poniżej znajduje się przykład pokazujący typy jawne i niejawne w Rust.
fn add_one(input: u8) -> u8 { input + 1}let four = add_one(3);
tutaj metodaadd_one
jest jednoznaczna z typem wejścia i typu wyjścia., Liczba1
dodawana tutaj jest domyślnie wykonanau8
liczba w czasie kompilacji, ponieważ kontekst pomaga wywnioskować typ i dodanie dlau8
jest zaimplementowane tylko do pracy zu8
. Ostatnia linia jest domyślnie wpisywana jako u8
, ponieważ sama metoda definiuje typ, który zostanie zwrócony.
Co można wywnioskować w Rust jest dość imponujące przy użyciu leków generycznych. Ale użycie wnioskowania jest ograniczone do rzeczy, które mogą być znane w czasie kompilacji., Jeśli nie może być znany podczas kompilacji, musisz jawnie zdefiniować typ w dowolnym momencie przypisania. Weź następującą definicję metody:
use std::ops::Add;fn add_both<T: Add>(a: T, b: T) -> T::Output { a + b}
tutaj T
może być dowolnym typem, który implementuje cechę Add
. Typ T::Output
jest definiowany, gdy cecha Add jest zdefiniowana dla konkretnego typu i jest ogólnie tym samym typem, co w tym przypadku T
. Teraz, jeśli podamy dwie liczby jako parametry, kompilator wywnioskuje z niego Typ.,
let x = add_both(3 , 4 ); // implicit typelet y: u8 = add_both(3u8 , 4u8 ); // explicit typelet z: u32 = add_both(3u32, 4u32); // explicit type
kiedy uruchamiam powyższy kodx
wnioskuje się, że jest to typi32
. Przykładyy
Iz
wymagają, aby typy parametrów wejściowych były znane, gdy zostaną podane do funkcji jako wnioskowanie dlaT::Output
niekoniecznie są takie same, jak to, co można wywnioskować jako. Domyślnie jest to i32
, a następnie przypisanie i32
jako u8
lub u32
jest po prostu błędne.,
języki pisane dynamicznie
teraz z językami pisanymi dynamicznie, musisz mniej martwić się o typy, per se, a więcej o obiekty lub zachowania niejawne lub jawne. Modelowanie kodu wokół obiektów, które mają takie samo zachowanie, jest czymś, co jest znane jako pisanie kaczek, które jest wyższą domeną myślenia w programowaniu obiektowym, gdzie obsługa tych obiektów jest niejawna. Podczas gdy modelowanie kodu wokół określonych klas obiektów jest podobne do używania jawnego lub niejawnego typowania., Ale kiedy akceptujesz dowolny rodzaj obiektu jako dane wejściowe, kod w tej sekcji musi albo obsługiwać różne obiekty jawnie, albo przekazać tę odpowiedzialność gdzie indziej.
dla wyjaśnienia, kiedy piszesz kod do obsługi różnych rzeczy, to piszesz jawny kod. Jednak gdy ten sam kod został już napisany i używasz go ponownie za pomocą prostego wywołania metody, zachowanie w tym nowym kontekście jest wtedy niejawne. Ukryte są rzeczy robione tak, jakby automatycznie i obsługiwane poza twoim obecnym zakresem.,
w języku Ruby większość typów ma konstrukcję do jawnej lub niejawnej konwersji. Chodzi o to, że ukryte metody konwersji mają być używane w niejawnych kontekstach, a jawne konwersje są przeznaczone dla programistów do pisania inline w znacznie większej liczbie kontekstów. Pozwól, że zademonstruję to na przykładzie.
# explicit"4".to_i + "5".to_i# => 9# implicitclass Seven def to_int 7 endendArray.new(Seven.new)# =>
tutaj wyraźny przykład sprawia, że czytelnik jest bardzo oczywisty, że konwertujemy obiektyString
na obiektInteger
I wykonujemy dodawanie między nimi., Przykład ten nie jest tak oczywisty dla czytelnika, ponieważ metoda Array.new
domyślnie wywołuje metodę to_int na dowolnym parametrze, który jest podany. Klasa Integer ma metodę to_int zdefiniowaną na każdej jej instancji, która po prostu zwraca self. Jeśli napiszesz 42.to_int
po prostu otrzymasz 42
. Użycie konwersji implicit jako zabezpieczenia wejściowego dla wywołań metod jest świetnym rozwiązaniem dla bezpieczeństwa typu. Oto, co się stanie, jeśli podasz niewłaściwy rodzaj obiektu jako wejście, które nie definiuje to_int
.,
Array.new("32")# TypeError (no implicit conversion of String into Integer)
nie tylko nie powiodło się, ale daje nam pomocny komunikat, że próbowano domyślnej konwersji i informuje klasę danego obiektu oraz klasę obiektu, której oczekuje. Implicit conversion methods w Ruby jest sposobem na powiedzenie, że ten obiekt naprawdę jest tym, czego oczekujesz. A konwersja jawna jest po prostu dokonaniem konwersji na typ oczekiwany.
Ruby ma domyślne i jawne opcje dla wielu swoich podstawowych obiektów.,
Ruby ma również kilka klas z metodami klasowymi, które albo wykonają ukrytą konwersję, albo zwrócą nil, a nazwa metody to try_convert
.
możemy podążać za przykładem Rubiego z Array.new
I mieć dobrą ochronę dla rodzaju parametrów wejściowych, które otrzymujemy, projektując Ukryte konwersje dla naszych własnych niestandardowych typów. W tym przykładzie, ponieważ to_f
jest jawną konwersją na liczbę zmiennoprzecinkową w Rubim, użyjemy as_
jako prefiksu zamiast to_
., Oto podstawowy przykład implicitness jako wzorzec bezpieczeństwa.
teraz pomoże to innym programistom, którzy używają klasyBar
, aby nie przekazywali jej jako niezgodnego parametru. Jest to zgodne z konwencją języka Ruby i powinno być znacznie łatwiejsze do zrozumienia dla programistów z bardziej pomocnymi błędami. Jeśli masz inne obiekty, które chcesz przekonwertować na obiekt Foo, możesz zdefiniować na nim metodęas_f
dla jawnej konwersji, a deweloper, który używa tego nowego obiektu, będzie jawny w użyciuBar.new(Baz.new.as_f)
., Zapewnia to, że kod będzie działał tak bardzo, jak Bar
I Foo
już działają.
podsumowanie
akt kodowania implicit i explicit oraz implicit i explicit jest definiowany przez kontekst wykonania dodatkowego zachowania lub ustawienia / odlewania typu. W szczególności metody niejawne lub jawne są definiowane przez konteksty, w których mają być używane. Kod ukryty może być bardzo miłym doświadczeniem, jeśli rzeczy są dobrze nazwane, ponieważ utrzymuje rzeczy proste.,
jednak kod ukryty, kod robiący rzeczy za kulisami dla ciebie, może być również trudnym problemem do rozwiązania, gdy zrobiony źle. Jawny kod sprawia, że kod jest jasny, gdy patrzysz na niego, ponieważ specyfika tego, co jest robione, jest już przedstawiona przed tobą i nie musisz szukać problemów gdzie indziej, ale ogólnie oznacza to dużo więcej pracy, pisząc go. Sama w sobie może stać się przytłaczająca, więc znalezienie odpowiedniej równowagi między nimi jest często najlepszym rozwiązaniem. Bądź jawny, gdy musisz, i Niejawny, gdy koncepcje projektowania i nazewnictwa są łatwe do zrozumienia., Zapewni to wygodniejsze doświadczenie programistyczne.