-
Notifications
You must be signed in to change notification settings - Fork 1k
Polish translation of the Scala tutorial #652
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
--- | ||
layout: tutorial | ||
title: Typy abstrakcyjne | ||
|
||
disqus: true | ||
|
||
tutorial: scala-tour | ||
num: 22 | ||
languages: [ba, es, ko, pl] | ||
language: pl | ||
tutorial-next: compound-types | ||
tutorial-previous: inner-classes | ||
--- | ||
|
||
W Scali, klasy są parametryzowane wartościami (parametry konstruktora) oraz typami (jeżeli klasa jest [generyczna](generic-classes.html)). Aby zachować regularność, zarówno typy jak i wartości są elementami klasy. Analogicznie mogą one być konkretne albo abstrakcyjne. | ||
|
||
Poniższy przykład definiuje wartość określaną przez abstrakcyjny typ będący elementem [cechy](traits.html) `Buffer`: | ||
|
||
```tut | ||
trait Buffer { | ||
type T | ||
val element: T | ||
} | ||
``` | ||
|
||
*Typy abstrakcyjne* są typami, które nie są jednoznacznie określone. W powyższym przykładzie wiemy tylko, że każdy obiekt klasy `Buffer` posiada typ `T`, ale definicja klasy `Buffer` nie zdradza jakiemu konkretnie typowi on odpowiada. Tak jak definicje wartości, możemy także nadpisać definicje typów w klasach pochodnych. Pozwala to nam na odkrywanie dodatkowych informacji o abstrakcyjnym typie poprzez zawężanie jego ograniczeń (które opisują możliwe warianty konkretnego typu). | ||
|
||
W poniższym programie definiujemy klasę `SeqBuffer`, która ogranicza możliwe typy `T` do pochodnych sekwencji `Seq[U]` dla nowego typu `U`: | ||
|
||
```tut | ||
abstract class SeqBuffer extends Buffer { | ||
type U | ||
type T <: Seq[U] | ||
def length = element.length | ||
} | ||
``` | ||
|
||
Cechy oraz [klasy](classes.html) z abstrakcyjnymi typami są często używane w połączeniu z anonimowymi klasami. Aby to zilustrować wykorzystamy program, w którym utworzymy bufor sekwencji ograniczony do listy liczb całkowitych: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would consider adding comma after |
||
|
||
```tut | ||
abstract class IntSeqBuffer extends SeqBuffer { | ||
type U = Int | ||
} | ||
|
||
object AbstractTypeTest1 extends App { | ||
def newIntSeqBuf(elem1: Int, elem2: Int): IntSeqBuffer = | ||
new IntSeqBuffer { | ||
type T = List[U] | ||
val element = List(elem1, elem2) | ||
} | ||
val buf = newIntSeqBuf(7, 8) | ||
println("length = " + buf.length) | ||
println("content = " + buf.element) | ||
} | ||
``` | ||
|
||
Typ zwracany przez metodę `newIntSeqBuf` nawiązuje do specjalizacji cechy `Buffer`, w której typ `U` jest równy `Int`. Podobnie w anonimowej klasie tworzonej w metodzie `newIntSeqBuf` określamy `T` jako `List[Int]`. | ||
|
||
Warto zwrócić uwagę na to, że często jest możliwa zamiana abstrakcyjnych typów w parametry typów klas i odwrotnie. Poniższy przykład stosuje wyłącznie parametry typów: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Without |
||
|
||
```tut | ||
abstract class Buffer[+T] { | ||
val element: T | ||
} | ||
abstract class SeqBuffer[U, +T <: Seq[U]] extends Buffer[T] { | ||
def length = element.length | ||
} | ||
object AbstractTypeTest2 extends App { | ||
def newIntSeqBuf(e1: Int, e2: Int): SeqBuffer[Int, Seq[Int]] = | ||
new SeqBuffer[Int, List[Int]] { | ||
val element = List(e1, e2) | ||
} | ||
val buf = newIntSeqBuf(7, 8) | ||
println("length = " + buf.length) | ||
println("content = " + buf.element) | ||
} | ||
``` | ||
|
||
Należy też pamiętać o zastosowaniu [adnotacji wariancji](variance.html). Inaczej nie byłoby możliwe ukrycie konkretnego typu sekwencji obiektu zwracanego przez metodę `newIntSeqBuf`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
--- | ||
layout: tutorial | ||
title: Adnotacje | ||
|
||
disqus: true | ||
|
||
tutorial: scala-tour | ||
num: 31 | ||
tutorial-next: default-parameter-values | ||
tutorial-previous: automatic-closures | ||
language: pl | ||
--- | ||
|
||
Adnotacje dodają meta-informacje do różnego rodzaju definicji. | ||
|
||
Podstawową formą adnotacji jest `@C` lub `@C(a1, ..., an)`. Tutaj `C` jest konstruktorem klasy `C`, który musi odpowiadać klasie `scala.Annotation`. Wszystkie argumenty konstruktora `a1, ..., an` muszą być stałymi wyrażeniami (czyli wyrażeniami takimi jak liczby, łańcuchy znaków, literały klasowe, enumeracje Javy oraz ich jednowymiarowe tablice). | ||
|
||
Adnotację stosuje się do pierwszej definicji lub deklaracji która po niej następuje. Możliwe jest zastosowanie więcej niż jednej adnotacji przed definicją lub deklaracją. Kolejność według której są one określone nie ma istotnego znaczenia. | ||
|
||
Znaczenie adnotacji jest zależne od implementacji. Na platformie Java, poniższe adnotacje domyślnie oznaczają: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There shouldn't be comma after |
||
|
||
| Scala | Java | | ||
| ------ | ------ | | ||
| [`scala.SerialVersionUID`](http://www.scala-lang.org/api/2.9.1/scala/SerialVersionUID.html) | [`serialVersionUID`](http://java.sun.com/j2se/1.5.0/docs/api/java/io/Serializable.html#navbar_bottom) (pole) | | ||
| [`scala.cloneable`](http://www.scala-lang.org/api/2.9.1/scala/cloneable.html) | [`java.lang.Cloneable`](http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Cloneable.html) | | ||
| [`scala.deprecated`](http://www.scala-lang.org/api/2.9.1/scala/deprecated.html) | [`java.lang.Deprecated`](http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Deprecated.html) | | ||
| [`scala.inline`](http://www.scala-lang.org/api/2.9.1/scala/inline.html) (since 2.6.0) | brak odpowiednika | | ||
| [`scala.native`](http://www.scala-lang.org/api/2.9.1/scala/native.html) (since 2.6.0) | [`native`](http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html) (słowo kluczowe) | | ||
| [`scala.remote`](http://www.scala-lang.org/api/2.9.1/scala/remote.html) | [`java.rmi.Remote`](http://java.sun.com/j2se/1.5.0/docs/api/java/rmi/Remote.html) | | ||
| [`scala.serializable`](http://www.scala-lang.org/api/2.9.1/index.html#scala.annotation.serializable) | [`java.io.Serializable`](http://java.sun.com/j2se/1.5.0/docs/api/java/io/Serializable.html) | | ||
| [`scala.throws`](http://www.scala-lang.org/api/2.9.1/scala/throws.html) | [`throws`](http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html) (słowo kluczowe) | | ||
| [`scala.transient`](http://www.scala-lang.org/api/2.9.1/scala/transient.html) | [`transient`](http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html) (słowo kluczowe) | | ||
| [`scala.unchecked`](http://www.scala-lang.org/api/2.9.1/scala/unchecked.html) (od 2.4.0) | brak odpowiednika | | ||
| [`scala.volatile`](http://www.scala-lang.org/api/2.9.1/scala/volatile.html) | [`volatile`](http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html) (słowo kluczowe) | | ||
| [`scala.reflect.BeanProperty`](http://www.scala-lang.org/api/2.9.1/scala/reflect/BeanProperty.html) | [`Design pattern`](http://docs.oracle.com/javase/tutorial/javabeans/writing/properties.html) | | ||
|
||
W poniższym przykładzie dodajemy adnotację `throws` do definicji metody `read` w celu obsługi rzuconego wyjątku w programie w Javie. | ||
|
||
> Kompilator Javy sprawdza czy program zawiera obsługę dla [wyjątków kontrolowanych](http://docs.oracle.com/javase/tutorial/essential/exceptions/index.html) poprzez sprawdzenie, które wyjątki mogą być wynikiem wykonania metody lub konstruktora. Dla każdego kontrolowanego wyjątku który może być wynikiem wykonania, adnotacja **throws** musi określić klasę tego wyjątku lub jedną z jej klas bazowych. | ||
> Ponieważ Scala nie pozwala na definiowanie wyjątków kontrolowanych, jeżeli chcemy obsłużyć wyjątek z kodu w Scali w Javie, należy dodać jedną lub więcej adnotacji `throws` określającej klasy wyjątków przez nią rzucanych. | ||
|
||
``` | ||
package examples | ||
import java.io._ | ||
class Reader(fname: String) { | ||
private val in = new BufferedReader(new FileReader(fname)) | ||
@throws(classOf[IOException]) | ||
def read() = in.read() | ||
} | ||
``` | ||
|
||
Poniższy program w Javie wypisuje zawartość pliku, którego nazwa jest podana jako pierwszy argument w metodzie `main`: | ||
|
||
``` | ||
package test; | ||
import examples.Reader; // Klasa Scali !! | ||
public class AnnotaTest { | ||
public static void main(String[] args) { | ||
try { | ||
Reader in = new Reader(args[0]); | ||
int c; | ||
while ((c = in.read()) != -1) { | ||
System.out.print((char) c); | ||
} | ||
} catch (java.io.IOException e) { | ||
System.out.println(e.getMessage()); | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Zakomentowanie adnotacji `throws` w klasie `Reader` spowoduje poniższy błąd kompilacji głównego programu w Javie: | ||
|
||
``` | ||
Main.java:11: exception java.io.IOException is never thrown in body of | ||
corresponding try statement | ||
} catch (java.io.IOException e) { | ||
^ | ||
1 error | ||
``` | ||
|
||
### Adnotacje Javy ### | ||
|
||
Java w wersji 1.5 wprowadziła możliwość definiowania metadanych przez użytkownika w postaci [adnotacji](https://docs.oracle.com/javase/tutorial/java/annotations/). Kluczową cechą adnotacji jest to, że polegają one na określaniu par nazwa-wartość w celu inicjalizacji jej elementów. Na przykład, jeżeli potrzebujemy adnotacji w celu śledzenia źródeł pewnej klasy, możemy ją zdefiniować w następujący sposób: | ||
|
||
``` | ||
@interface Source { | ||
public String URL(); | ||
public String mail(); | ||
} | ||
``` | ||
|
||
I następnie zastosować w taki sposób: | ||
|
||
``` | ||
@Source(URL = "http://coders.com/", | ||
mail = "[email protected]") | ||
public class MyClass extends HisClass ... | ||
``` | ||
|
||
Zastosowanie adnotacji w Scali wygląda podobnie jak wywołanie konstruktora, gdzie wymagane jest podanie nazwanych argumentów: | ||
|
||
``` | ||
@Source(URL = "http://coders.com/", | ||
mail = "[email protected]") | ||
class MyScalaClass ... | ||
``` | ||
|
||
Składnia ta może się wydawać nieco nadmiarowa, jeżeli adnotacja składa się tylko z jednego elementu (bez wartości domyślnej), zatem jeżeli nazwa pola jest określona jako `value`, może być ona stosowana w Javie stosując składnię podobną do konstruktora: | ||
|
||
``` | ||
@interface SourceURL { | ||
public String value(); | ||
public String mail() default ""; | ||
} | ||
``` | ||
|
||
Następnie ją można zastosować: | ||
|
||
``` | ||
@SourceURL("http://coders.com/") | ||
public class MyClass extends HisClass ... | ||
``` | ||
|
||
W tym przypadku, Scala daje taką samą możliwość: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Without comma after |
||
|
||
``` | ||
@SourceURL("http://coders.com/") | ||
class MyScalaClass ... | ||
``` | ||
|
||
Element `mail` został zdefiniowany z wartością domyślną, zatem nie musimy jawnie określać wartości dla niego. Jednakże, jeżeli chcemy tego dokonać, Java nie pozwala nam na mieszanie tych styli: | ||
|
||
``` | ||
@SourceURL(value = "http://coders.com/", | ||
mail = "[email protected]") | ||
public class MyClass extends HisClass ... | ||
``` | ||
|
||
Scala daje nam większą elastyczność w tym aspekcie: | ||
|
||
``` | ||
@SourceURL("http://coders.com/", | ||
mail = "[email protected]") | ||
class MyScalaClass ... | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
--- | ||
layout: tutorial | ||
title: Funkcje anonimowe | ||
|
||
disqus: true | ||
|
||
tutorial: scala-tour | ||
num: 6 | ||
language: pl | ||
tutorial-next: higher-order-functions | ||
tutorial-previous: mixin-class-composition | ||
--- | ||
|
||
Scala posiada lekką składnię pozwalającą na definiowanie funkcji anonimowych. Poniższe wyrażenie tworzy funkcję następnika dla liczb całkowitych: | ||
|
||
```tut | ||
(x: Int) => x + 1 | ||
``` | ||
|
||
Jest to krótsza forma deklaracji anonimowej klasy: | ||
|
||
```tut | ||
new Function1[Int, Int] { | ||
def apply(x: Int): Int = x + 1 | ||
} | ||
``` | ||
|
||
Możliwe jest także zdefiniowanie funkcji z wieloma parametrami: | ||
|
||
```tut | ||
(x: Int, y: Int) => "(" + x + ", " + y + ")" | ||
``` | ||
|
||
lub też bez parametrów: | ||
|
||
```tut | ||
() => { System.getProperty("user.dir") } | ||
``` | ||
|
||
Istnieje także prosty sposób definicji typów funkcji. Dla powyższych funkcji można je określić w następujący sposób: | ||
|
||
``` | ||
Int => Int | ||
(Int, Int) => String | ||
() => String | ||
``` | ||
|
||
Jest to skrócona forma dla poniższych typów: | ||
|
||
``` | ||
Function1[Int, Int] | ||
Function2[Int, Int, String] | ||
Function0[String] | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
--- | ||
layout: tutorial | ||
title: Automatyczna konstrukcja domknięć | ||
|
||
disqus: true | ||
|
||
tutorial: scala-tour | ||
num: 30 | ||
language: pl | ||
tutorial-next: annotations | ||
tutorial-previous: operators | ||
--- | ||
|
||
Scala pozwala na przekazywanie funkcji bezparametrycznych jako argumenty dla metod. Kiedy tego typu metoda jest wywołana, właściwe parametry dla funkcji bezparametrycznych nie są ewaluowane i przekazywana jest pusta funkcja, która enkapsuluje obliczenia odpowiadającego parametru (tzw. *wywołanie-przez-nazwę*). | ||
|
||
Poniższy kod demonstruje działanie tego mechanizmu: | ||
|
||
```tut | ||
object TargetTest1 extends App { | ||
def whileLoop(cond: => Boolean)(body: => Unit): Unit = | ||
if (cond) { | ||
body | ||
whileLoop(cond)(body) | ||
} | ||
var i = 10 | ||
whileLoop (i > 0) { | ||
println(i) | ||
i -= 1 | ||
} | ||
} | ||
``` | ||
|
||
Funkcja `whileLoop` pobiera dwa parametry: `cond` i `body`. Kiedy funkcja jest aplikowana, jej właściwe parametry nie są ewaluowane. Lecz gdy te parametry są wykorzystane w ciele `whileLoop`, zostanie ewaluowana niejawnie utworzona funkcja, zwracająca ich prawdziwą wartość. Zatem metoda `whileLoop` implementuje rekursywnie pętlę while w stylu Javy. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Without comma after |
||
|
||
Możemy połączyć ze sobą wykorzystanie [operatorów infiksowych/postfiksowych](operators.html) z tym mechanizmem aby utworzyć bardziej złożone wyrażenia. | ||
|
||
Oto implementacja pętli w stylu wykonaj-dopóki: | ||
|
||
```tut | ||
object TargetTest2 extends App { | ||
def loop(body: => Unit): LoopUnlessCond = | ||
new LoopUnlessCond(body) | ||
protected class LoopUnlessCond(body: => Unit) { | ||
def unless(cond: => Boolean) { | ||
body | ||
if (!cond) unless(cond) | ||
} | ||
} | ||
var i = 10 | ||
loop { | ||
println("i = " + i) | ||
i -= 1 | ||
} unless (i == 0) | ||
} | ||
``` | ||
|
||
Funkcja `loop` przyjmuje ciało pętli oraz zwraca instancję klasy `LoopUnlessCond` (która enkapsuluje to ciało). Warto zwrócić uwagę, że ciało tej funkcji nie zostało jeszcze ewaluowane. Klasa `LoopUnlessCond` posiada metodę `unless`, którą możemy wykorzystać jako *operator infiksowy*. W ten sposób, uzyskaliśmy całkiem naturalną składnię dla naszej nowej pętli: `loop { < stats > } unless ( < cond > )`. | ||
|
||
Oto wynik działania programu `TargetTest2`: | ||
|
||
``` | ||
i = 10 | ||
i = 9 | ||
i = 8 | ||
i = 7 | ||
i = 6 | ||
i = 5 | ||
i = 4 | ||
i = 3 | ||
i = 2 | ||
i = 1 | ||
``` | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There shouldn't be
,
afterScali
, tbh.