From 8c4b40736009d7e77c28888aabb98d561f40bf33 Mon Sep 17 00:00:00 2001 From: Andrea Date: Fri, 6 Nov 2020 20:25:59 +0100 Subject: [PATCH 1/3] Added tuples.md Italian translation --- _it/tour/tuples.md | 88 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 _it/tour/tuples.md diff --git a/_it/tour/tuples.md b/_it/tour/tuples.md new file mode 100644 index 0000000000..4bd5f2f0fe --- /dev/null +++ b/_it/tour/tuples.md @@ -0,0 +1,88 @@ +--- +layout: tour +title: Tuples +partof: scala-tour + +num: 8 +next-page: mixin-class-composition +previous-page: traits +topics: tuples +language: it +--- +Traduzione a cura di: Andrea Mucciarelli (https://github.com/IowU) + + +In Scala, una tupla è un valore che contiene un numero fisso di elementi, ognuno +con il proprio tipo. Le tuple sono immutabili. + +Le tuple sono particolarmente utili per restituire valori multipli da un methodo. + +Una tupla con due elementi può essere creata come segue: + +```tut +val ingredient = ("Sugar" , 25) +``` + +Questo creerà una tupla contenente un elemento di tipo `String` e uno di tipo `Int`. + +Il tipo inferito di `ingredient` è `(String, Int)`, che è un'abbreviazione per `Tuple2[String, Int]`. + +Per rappresentare le tuple, scala ha una serie di classi: `Tuple2`, `Tuple3`, ecc., fino a `Tuple22` (compreso). +Ogni classe ha un numero di tipi di parametri uguali al numero dei suoi elementi. + +## Accedere agli elementi + +Un modo per accedere agli elementi della tupla è per posizione. I singoli +elementi sono chiamati, in questo caso, `_1`, `_2`, e così via. Notare che +il primo elemento è richiamato tramite `_1`, e non `_0` come ci si potrebbe aspettare (NDT) + +```tut +println(ingredient._1) // Sugar +println(ingredient._2) // 25 +``` + +## Pattern matching per le tuple + +Una tupla può essere scomposta usando il pattern matching: + +```tut +val (name, quantity) = ingredient +println(name) // Sugar +println(quantity) // 25 +``` + +In questo esempio il tipo inferito di `name` è `String`, mentre quello di +`quantity` è `Int`. + +Di seguito un altro esempio di pattern matching applicato alle tuple: + +```tut +val planets = + List(("Mercury", 57.9), ("Venus", 108.2), ("Earth", 149.6), + ("Mars", 227.9), ("Jupiter", 778.3)) +planets.foreach{ + case ("Earth", distance) => + println(s"Our planet is $distance million kilometers from the sun") + case _ => +} +``` + +Oppure, usando le `for` comprehension: + +```tut +val numPairs = List((2, 5), (3, -7), (20, 56)) +for ((a, b) <- numPairs) { + println(a * b) +} +``` + +## Tuple e case class + +Gli utenti a volte trovano difficile scegliere tra tuple e case class. Le case class hanno elementi identificabili da un nome. I nomi possono +facilitare ed aumentare la leggibilità di alcuni pezzi di codice. Nell'esempio sopra, avremmo potuto definire una case class +`case class Planet(name: String, distance: Double)` invece di usare le tuple. + + +## Altre risorse + +* Potete trovare più informazioni sulle tuple al seguente link: [Scala Book](/overviews/scala-book/tuples.html) From c6241f3a20b2a8386d370be2a35c33da267f5674 Mon Sep 17 00:00:00 2001 From: Andrea Date: Tue, 17 Nov 2020 11:12:15 +0100 Subject: [PATCH 2/3] Added basics.md italian translation --- _it/tour/basics.md | 331 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 331 insertions(+) create mode 100644 _it/tour/basics.md diff --git a/_it/tour/basics.md b/_it/tour/basics.md new file mode 100644 index 0000000000..d5e51b3eb3 --- /dev/null +++ b/_it/tour/basics.md @@ -0,0 +1,331 @@ +--- +layout: tour +title: Basics +partof: scala-tour + +num: 2 +next-page: unified-types +previous-page: tour-of-scala +language: it +--- +Traduzione a cura di: Andrea Mucciarelli (https://github.com/IowU) + + +In questa pagina tratteremo le basi di Scala. + +## Provare Scala nel browser + +È possibile eseguire Scala nel proprio browser con _ScalaFiddle_. Questo è un metodo facile e che non richiede alcun setup +per testare il proprio codice Scala: + +1. Andare all'indirizzo [https://scalafiddle.io](https://scalafiddle.io). +2. Incolla `println("Hello, world!")` nella sezione di sinistra. +3. Clicca __Run__. L'output apparirà nella sezione di destra. + +_ScalaFiddle_ è integrato direttamente con alcuni degli esempi di codice di questa documentazione; se vedi il pulsante __RUN__ in uno degli esempi seguenti, cliccalo per testare direttamente il codice. + +## Espressioni + +Le espressioni sono degli enunciati calcolabili: +``` +1 + 1 +``` +Puoi far mostrare il risultato delle espressioni usando `println`: + +{% scalafiddle %} +```tut +println(1) // 1 +println(1 + 1) // 2 +println("Hello!") // Hello! +println("Hello," + " world!") // Hello, world! +``` +{% endscalafiddle %} + +### Valori + +Puoi dare un nome ai risultati delle espressioni usando la parola chiave `val`: + +```tut +val x = 1 + 1 +println(x) // 2 +``` + +I risultati a cui è stato attribuito un nome, come `x` nell'esempio sopra, sono chiamati valori. +Richiamare un valore già definito non aziona il suo ricalcolo. + +I valori non possono essere riassegnati: + +```tut:fail +x = 3 // Questo non può essere compilato. +``` + +Il tipo di un valore può essere omesso e [inferito](https://docs.scala-lang.org/tour/type-inference.html), oppure +può essere dichiarato esplicitamente: + +```tut +val x: Int = 1 + 1 +``` + +Da notare che la dichiarazione del tipo `Int` viene dopo l'identificativo `x` e dopo `:`. + +### Variabili + +Le variabili sono simili ai valori, ma a differenza di questi ultimi li puoi riassegnare. Puoi definire una variabile con +la parola chiave `var`. + +```tut +var x = 1 + 1 +x = 3 // Questo compila perchè "x" è stato dichiarato con la parola chiave "var". +println(x * x) // 9 +``` + +Come per i valori, il tipo di una variabile può essere omesso e [inferito](https://docs.scala-lang.org/tour/type-inference.html), oppure può essere dichiarato esplicitamente: + +```tut +var x: Int = 1 + 1 +``` + +## Blocchi di codice + +Puoi combinare espressioni inserendole tra `{}`. Chiamiamo questo un blocco (di codice). + +Il risultato dell'ultima espressione nel blocco sarà anche il risultato dell'intero blocco: + +```tut +println({ + val x = 1 + 1 + x + 1 +}) // 3 +``` + +## Funzioni + +Le funzioni sono espressioni che hanno parametri e prendono argomenti in input. + +Puoi definire una funzione anonima (ossia una funzione che non ha un nome) che restituisce un determinato intero più uno: + +```tut +(x: Int) => x + 1 +``` + +A sinistra di `=>` c'è una lista di parametri. Sulla destra è presente un'espressione che coinvolge questi parametri. + +Puoi anche dare un nome alle funzioni: + +{% scalafiddle %} +```tut +val addOne = (x: Int) => x + 1 +println(addOne(1)) // 2 +``` +{% endscalafiddle %} + +Una funzione può avere parametri multipli: + +{% scalafiddle %} +```tut +val add = (x: Int, y: Int) => x + y +println(add(1, 2)) // 3 +``` +{% endscalafiddle %} + +O anche non averne affatto: + +```tut +val getTheAnswer = () => 42 +println(getTheAnswer()) // 42 +``` + +## Metodi + +I metodi appaiono simili alla funzioni per aspetto e funzionalità, ma ci sono alcune differenze importanti. + +I metodi sono definiti con la parola chiave `def`. `def` è seguita da un nome, un parametro o una lista di parametri, il tipo di ritorno del metodo, e il suo corpo: + +{% scalafiddle %} +```tut +def add(x: Int, y: Int): Int = x + y +println(add(1, 2)) // 3 +``` +{% endscalafiddle %} + +Da notare come il tipo di ritorno `Int` sia dichiarato _dopo_ l'elenco dei parametri da passare in input, e dopo un `:`. + +Un metodo può avere più liste di parametri: + +{% scalafiddle %} +```tut +def addThenMultiply(x: Int, y: Int)(multiplier: Int): Int = (x + y) * multiplier +println(addThenMultiply(1, 2)(3)) // 9 +``` +{% endscalafiddle %} + +Oppure nulla: + +```tut +def name: String = System.getProperty("user.name") +println("Hello, " + name + "!") +``` + +Ci sono altre differenze, ma per ora puoi pensare ai metodi come qualcosa di simile alle funzioni. + +Anche i metodi possono avere espressioni su più righe (un blocco di codice): + +{% scalafiddle %} +```tut +def getSquareString(input: Double): String = { + val square = input * input + square.toString +} +println(getSquareString(2.5)) // 6.25 +``` +{% endscalafiddle %} + +L'ultima espressione nel corpo del metodo sarà il valore di ritorno di quest'ultimo. (Scala possiede tuttavia la parola chiave `return`, ma è raramente usata.) + +## Classi + +Puoi definire delle classi con la parola chiave `class`, seguita dal suo nome e dai parametri del costruttore: + +```tut +class Greeter(prefix: String, suffix: String) { + def greet(name: String): Unit = + println(prefix + name + suffix) +} +``` + +Il tipo di ritorno del metodo `greet` è `Unit`, stante a significare che non c'è nulla di interessante da restituire. +È usato in maniera quasi uguale al `void` di Java e C. (Una differenza è che, poichè un'espressione in Scala deve avere un qualche valore, in realtà c'è un valore singleton di tipo Unit, indicato come `()`, ma non fornisce alcuna informazione.) + +Puoi instanziare una classe con la parola chiave `new`: + +```tut +val greeter = new Greeter("Hello, ", "!") +greeter.greet("Scala developer") // Hello, Scala developer! +``` +Tratteremo le classi più in dettaglio in [seguito](classes.html). + +## Classi case (case classes) + +Scala possiede un tipo speciale di classe chiamata classe "case". Di default, un'istanza di una classe case è immutabile, e sono comparate in base al valore (a differenza delle classi normali, le cui istanze sono comprate in base ai loro riferimenti in memoria). Questo le rende molto utili nel [pattern matching](https://docs.scala-lang.org/tour/pattern-matching.html#matching-on-case-classes). + +Puoi definire le classi case con le parole chiave `case class`: + +```tut +case class Point(x: Int, y: Int) +``` + +Puoi instanziare le classi case _senza_ la parola chiave `new`: + +```tut +val point = Point(1, 2) +val anotherPoint = Point(1, 2) +val yetAnotherPoint = Point(2, 2) +``` + +Le istanze di classi case sono confrontate usando il valore, e non il riferimento in memoria: + +```tut +if (point == anotherPoint) { + println(point + " e " + anotherPoint + " sono uguali.") +} else { + println(point + " e " + anotherPoint + " sono differenti.") +} // Point(1,2) e Point(1,2) sono uguali. + +if (point == yetAnotherPoint) { + println(point + " e " + yetAnotherPoint + " sono uguali.") +} else { + println(point + " e " + yetAnotherPoint + " sono differenti.") +} // Point(1,2) e Point(2,2) sono differenti. +``` + +C'è molto di più riguardo alle classi case, e siamo convinti che finirai per amarle! +Verranno esaminate più nel dettaglio in [seguito](case-classes.html). + +## Oggetti (Objects) + +Gli oggetti sono delle singole istanze: come se fossero delle singole istanze di classi aventi lo stesso nome. + +Puoi definire gli oggetti con la parola chiave `object`: + +```tut +object IdFactory { + private var counter = 0 + def create(): Int = { + counter += 1 + counter + } +} +``` + +Puoi accedere ad un oggetto facendo riferimento al suo nome: + +```tut +val newId: Int = IdFactory.create() +println(newId) // 1 +val newerId: Int = IdFactory.create() +println(newerId) // 2 +``` + +Tratteremo gli oggetti più in dettaglio in [seguito](singleton-objects.html). + +## Tratti + +I tratti sono dei tipi astratti di dati contenenti determinati campi e metodi. Secondo le regole di ereditarietà di Scala, una classe può estendere solo *una* classe, ma può estendere più tratti. + +Puoi definire i tratti con la parola chiave `trait`: + +```tut +trait Greeter { + def greet(name: String): Unit +} +``` + +I tratti possono anche avere implementazioni di default: + +{% scalafiddle %} +```tut +trait Greeter { + def greet(name: String): Unit = + println("Hello, " + name + "!") +} +``` + +Puoi estendere i tratti con la parola chiave `extends` e sovrascrivere (override) un'implementazione con la parola chiave `override`: + +```tut +class DefaultGreeter extends Greeter + +class CustomizableGreeter(prefix: String, postfix: String) extends Greeter { + override def greet(name: String): Unit = { + println(prefix + name + postfix) + } +} + +val greeter = new DefaultGreeter() +greeter.greet("Scala developer") // Hello, Scala developer! + +val customGreeter = new CustomizableGreeter("How are you, ", "?") +customGreeter.greet("Scala developer") // How are you, Scala developer? +``` +{% endscalafiddle %} + +Nell'esempio sopra, `DefaultGreeter` estende un singolo tratto, ma avrebbe potuto estenderne un numero maggiore. + +Esamineremo i tratti in dettaglio in [seguito](traits.html). + +## Il metodo principale (metodo main) + +Il metodo principale è il punto di ingresso di un programma Scala. La Macchina Virtuale Java (Java Virtual Machine) necessita di un particolare metodo principale, chiamato `main`, che prende un argomento: un array di stringhe. + +Usando un oggetto, puoi definire il metodo principale come segue: + +```tut +object Main { + def main(args: Array[String]): Unit = + println("Hello, Scala developer!") +} +``` + +## Altre risorse + +* [Scala book](/overviews/scala-book/prelude-taste-of-scala.html) per una trattazione generale. From cba8198c20e9e6006dd7165a4d3f78c7b2e15860 Mon Sep 17 00:00:00 2001 From: Andrea Date: Wed, 25 Nov 2020 10:06:04 +0100 Subject: [PATCH 3/3] More italian translations for tour tutorials --- _it/tour/annotations.md | 128 +++++++++++++++++++++++++++++++++ _it/tour/by-name-parameters.md | 39 ++++++++++ _it/tour/case-classes.md | 61 ++++++++++++++++ _it/tour/classes.md | 111 ++++++++++++++++++++++++++++ 4 files changed, 339 insertions(+) create mode 100644 _it/tour/annotations.md create mode 100644 _it/tour/by-name-parameters.md create mode 100644 _it/tour/case-classes.md create mode 100644 _it/tour/classes.md diff --git a/_it/tour/annotations.md b/_it/tour/annotations.md new file mode 100644 index 0000000000..aaa02a6d0c --- /dev/null +++ b/_it/tour/annotations.md @@ -0,0 +1,128 @@ +--- +layout: tour +title: Annotations +partof: scala-tour + +num: 34 +next-page: packages-and-imports +previous-page: by-name-parameters +language: it +--- +Traduzione a cura di: Andrea Mucciarelli (https://github.com/IowU) + +Le annotazioni associano meta-informazioni alle definizioni. Per esempio l'annotazione `@deprecated` prima di un metodo porta il compilatore a stampare un avvertimento se quel metodo è usato. + +``` +object DeprecationDemo extends App { + @deprecated("deprecation message", "release # which deprecates method") + def hello = "hola" + + hello +} +``` +Il codice verrà comunque compilato, ma il compilatore ci restituirà un avvertimento: "there was one deprecation warning". + +Una clausola di annotazione si applica alla prima definizione, o dichiarazione, che la segue. Più di un'annotazione può precedere una definizione e/o dichiarazione. L'ordine con le quali appaiono non è rilevante. + +## Annotazioni che assicurano la correttezza del codice +Alcune annotazioni faranno si che ci venga restituito un errore di compilazione se una o più condizioni non sono rispettate. Ad esempio, l'annotazione `@tailrec` assicura che il metodo che la segue sarà [tail-recursive](https://en.wikipedia.org/wiki/Tail_call). La tail-recursion può far si che i requisiti di memoria siano tenuti costanti. Di seguito un esempio in cui viene usata su un metodo che calcola il fattoriale di un numero: + +```tut +import scala.annotation.tailrec + +def factorial(x: Int): Int = { + + @tailrec + def factorialHelper(x: Int, accumulator: Int): Int = { + if (x == 1) accumulator else factorialHelper(x - 1, accumulator * x) + } + factorialHelper(x, 1) +} +``` + +Il metodo `factorialHelper` è annotato con `@tailrec`, che ci assicura il suo essere tail-recursive. Se cambiassimo l'implementazione del metodo come di seguito, avremmo un errore: + +``` +import scala.annotation.tailrec + +def factorial(x: Int): Int = { + @tailrec + def factorialHelper(x: Int): Int = { + if (x == 1) 1 else x * factorialHelper(x - 1) + } + factorialHelper(x) +} +``` +Otterremmo il messaggio "Recursive call not in tail position". + + +## Annotazioni che influenzano la generazione del codice +Alcune annotazioni come `@inline` influenzano il codice generato (ad esempio il tuo file jar potrebbe avere dei byte diversi se non fosse stata usata l'annotazione). Effettuare un azione di inline vuol dire inserire il codice nel corpo del metodo al momento della chiamata. Il bytecode risultante è più lungo, ma potrebbe portare ad un'esecuzione più rapida. Usare l'annotazione `@inline` non assicura però che il metodo sarà di tipo inline, ma porterà il compilatore a renderlo tale se e solo se saranno rispettate alcune condizioni sulla dimensione del codice generato. + +### Annotazioni Java ### +Bisogna porre attenzione alla sintassi delle annotazioni quando si scrive del codice Scala che si interfaccia con codice Java. +**Nota:** Assicurati di usare l'opzione `-target:jvm-1.8` con le annotazioni Java. + +Java possiede dei metadati, dichiarati dagli utenti, sotto forma di [annotazioni](https://docs.oracle.com/javase/tutorial/java/annotations/). Una caratteristica chiave delle annotazioni è che esse hanno bisogno di specificare delle coppie nome-valore per inizializzare i propri elementi. Per esempio, se necessitiamo che un'annotazione tracci la sorgente di una certa classem possiamo definirla come segue: + +``` +@interface Source { + public String URL(); + public String mail(); +} +``` + +E successivamente applicarla: + +``` +@Source(URL = "https://coders.com/", + mail = "support@coders.com") +public class MyClass extends TheirClass ... +``` + +Usare un'annotazione in Scala è simile all'invocazione di un costruttore, poichè per istanziare un'annotazione Java bisogna specificare il nome degli argomenti e i loro valori: + +``` +@Source(URL = "https://coders.com/", + mail = "support@coders.com") +class MyScalaClass ... +``` + +Questa sintassi può essere fastidiosa se l'annotazione contiene un solo elemento (senza che abbia un valore di default), pertanto, per convenzione, se il nome è sepcificato come `value` può essere applicato in Java usando una sintassi simile a quella dei costruttori: + +``` +@interface SourceURL { + public String value(); + public String mail() default ""; +} +``` + +E successivamente applicarla come segue + +``` +@SourceURL("https://coders.com/") +public class MyClass extends TheirClass ... +``` + +In questo caso, Scala fornisce la stessa opzione + +``` +@SourceURL("https://coders.com/") +class MyScalaClass ... +``` + +L'elemento `mail` è stat specificato con un valore di dafault in modo che non dobbiamo per forza fornirne esplicitamente uno. Se però ci servisse di fornire tale valore non possiamo mixare i due stili in Java: + +``` +@SourceURL(value = "https://coders.com/", + mail = "support@coders.com") +public class MyClass extends TheirClass ... +``` + +Scala fornisce più flessibilità a riguardo: + +``` +@SourceURL("https://coders.com/", + mail = "support@coders.com") + class MyScalaClass ... +``` diff --git a/_it/tour/by-name-parameters.md b/_it/tour/by-name-parameters.md new file mode 100644 index 0000000000..bd4a5bfb0f --- /dev/null +++ b/_it/tour/by-name-parameters.md @@ -0,0 +1,39 @@ +--- +layout: tour +title: By-name Parameters +partof: scala-tour + +num: 33 +next-page: annotations +previous-page: operators +language: it +--- +Traduzione a cura di: Andrea Mucciarelli (https://github.com/IowU) + +I parametri _By-name parameters_ vengono calcolati ad ogni loro utilizzo. Non saranno calcolati affatto nel caso rimanessero inutilizzati. Questo processo è analogo al sostituire i parametri by-name con le espressioni fornite, e sono in opposizioni ai parametri _by-value parameters_. Per far si che un parametro diventi di tipo by-name basta inserire `=>` prima della dichiarazione del suo tipo. +```tut +def calculate(input: => Int) = input * 37 +``` +I parametri by-name hanno il vantaggio di non venire calcolati se non sono utilizzati nel corpo della funzione; d'altra parte i parametri by-value hanno invece il vantaggio di venire calcolati solo una volta. + +Di seguito un esempio di implementazione di un loop while usando pararmetry by-name: + +```tut +def whileLoop(condition: => Boolean)(body: => Unit): Unit = + if (condition) { + body + whileLoop(condition)(body) + } + +var i = 2 + +whileLoop (i > 0) { + println(i) + i -= 1 +} // Mostrerà a schermo 2 1 +``` +Il metodo `whileLoop` utilizza diverse liste di parametri per ricevere una condizione, e un corpo che agirà da corpo del loop. Se `condition` è vera, allora `body` viene eseguito e verrà fatta una chiamata ricorsiva alla funzione whileLoop. Se `condition` dovesse essere falsa, `body` non verrà mai calcolato; questo perchè abbiamo anteposto `=>` al datatype di `body`. + +Quando forniamo la condizione `i > 0` come `condition` e `println(i); i-=1` come `body`, la funzione si comporterà come un classico loop while presente in molti linguaggi di programmazione. + +Questa caratteristica di ritardare il calcolo di un parametro finchè questo non viene effettivamente usato può aiutare ad ottimizzare le performance nel caso in cui il calcolo del parametro richiedesse molte risore, o se il codice venisse inserito in operazioni di lunga durata. diff --git a/_it/tour/case-classes.md b/_it/tour/case-classes.md new file mode 100644 index 0000000000..0e8997e981 --- /dev/null +++ b/_it/tour/case-classes.md @@ -0,0 +1,61 @@ +--- +layout: tour +title: Case Classes +partof: scala-tour + +num: 13 +next-page: pattern-matching +previous-page: multiple-parameter-lists +prerequisite-knowledge: classes, basics, mutability +language: it +--- +Traduzione a cura di: Andrea Mucciarelli (https://github.com/IowU) + +Le classi case (_case classes_) sono simili alle classi tradizionali, ma con alcune importanti differenze. Le classi case si prestano bene per modellare dati immutabili. Potrai vedere la loro utilità leggendo la pagina relativa al [pattern matching](pattern-matching.html). + +## Definire una classe case +La definizione più piccola di una classe case richiede solamente la parola chiave `case class`, il nome che le si vuole assegnare e una lista di parametri (che potrebbe anche essere vuota): +```tut +case class Book(isbn: String) + +val frankenstein = Book("978-0486282114") +``` +Notare come non sia stata usata la parola chiave `new` per istanziare la classe case `Book`: questo perchè queste particolari classi hanno un'implementazione di default del metodo `apply` che gestisce la costruzione dell'oggetto. + +Quando crei una classe case con parametri, i parametri sono pubblici e di tipo `val`. +``` +case class Message(sender: String, recipient: String, body: String) +val message1 = Message("guillaume@quebec.ca", "jorge@catalonia.es", "Ça va ?") + +println(message1.sender) // Restituirà a schermo guillaume@quebec.ca +message1.sender = "travis@washington.us" // Questa linea di codice non si compilerà +``` +Non puoi riassegnare `message1.sender` perchè è un `val` (quindi immutabile). È comunque possibile definire i parametri come `var`, ma questa è una pratica che viene disincentivata per quanto riguarda le classi case. + +## Confronti +Le istanze delle classi case sono comparate a livello di strutture, e non di riferimenti in memoria: +```tut +case class Message(sender: String, recipient: String, body: String) + +val message2 = Message("jorge@catalonia.es", "guillaume@quebec.ca", "Com va?") +val message3 = Message("jorge@catalonia.es", "guillaume@quebec.ca", "Com va?") +val messagesAreTheSame = message2 == message3 // true +``` +Anche se `message2` e `message3` fanno riferimenti ad oggetti allocati in spazi differenti in memoria, il valore di ognuno di essi è uguale. + +## Effettuare una copia +Si può creare una copia si un'istanza di una classe case semplicemente utilizzando il metodo `copy`. È possibile inoltre cambiare gli argomenti del costruttore: +```tut +case class Message(sender: String, recipient: String, body: String) +val message4 = Message("julien@bretagne.fr", "travis@washington.us", "Me zo o komz gant ma amezeg") +val message5 = message4.copy(sender = message4.recipient, recipient = "claire@bourgogne.fr") +message5.sender // travis@washington.us +message5.recipient // claire@bourgogne.fr +message5.body // "Me zo o komz gant ma amezeg" +``` +Il destinarario di `message4` è usato come mittente di `message5`, ma il `body` di `message4` è stato copiato direttamente. +The recipient of `message4` is used as the sender of `message5` but the `body` of `message4` was copied directly. + +## Altre risorse + +* Per saperne di più sulle classi case puoi leggere il relativo capitolo presente in [Scala Book](/overviews/scala-book/case-classes.html) diff --git a/_it/tour/classes.md b/_it/tour/classes.md new file mode 100644 index 0000000000..b1b4285bae --- /dev/null +++ b/_it/tour/classes.md @@ -0,0 +1,111 @@ +--- +layout: tour +title: Classes +partof: scala-tour + +num: 4 +next-page: default-parameter-values +previous-page: unified-types +topics: classes +prerequisite-knowledge: no-return-keyword, type-declaration-syntax, string-interpolation, procedures +language: it +--- +Traduzione a cura di: Andrea Mucciarelli (https://github.com/IowU) + +In Scala le classi sono dei modelli per creare oggetti. Possono contenere metodi, valori, variabili, tipi, oggetti, tratti e classi che sono chiamate _members_. Tipi, oggetti e tratti verranno trattati in dettaglio in altre pagine. + +## Definire una classe +La classe più piccola che si può definire consiste semplicemente nella parola chiave `class` seguita dal nome che si vuole dare ad essa. Per convenzione i nomi delle classi hanno la prima lettera in maiuscolo. +```tut +class User + +val user1 = new User +``` +La parola chiave `new` è usata per creare un'istanza della classe. `User` ha un costruttore di default che non prende argomenti, dal momento che non è stato definito un costruttore dall'utente. Di solito però una classe possiede un costruttore e un corpo, pertanto di seguito viene fornito un esempio di definizione di una classe per un punto geometrico in 2D: + +```tut +class Point(var x: Int, var y: Int) { + + def move(dx: Int, dy: Int): Unit = { + x = x + dx + y = y + dy + } + + override def toString: String = + s"($x, $y)" +} + +val point1 = new Point(2, 3) +println(point1.x) // 2 +println(point1) // prints (2, 3) +``` + +La classe `Point` ha quattro membri: le variabili `x` e `y`, e i metodi `move` e `toString`. A differenza di molti altri linguaggi di programmazioni, il costruttore primario è già presente al momento della definizione dei parametri richiesti per l'istanziamento della classe, ossia `(var x: Int, var y: Int)`. Il metodo `move` prende in input due interi e restituisce il valore `()` di tipo Unit, che non fornisce alcuna informazione utile. Unit può essere pensato come ad un equivalente di `void` nei linguaggi di tipo Java. `toString` invece non prende argomenti in input ma restituisce un valore di tipo `String`. Poichè il metodo `toString` qui definito va a sovrascrivere il metodo `toString` ereditato da [`AnyRef`](unified-types.html), viene segnato con la parola chiave `override`. + +## Costruttori + +I costruttori possono avere parametri opzionali, nel qual caso viene loro fornito un valore di default: + +```tut +class Point(var x: Int = 0, var y: Int = 0) + +val origin = new Point // In questo caso x ed y avranno entrambi valore 0 +val point1 = new Point(1) +println(point1.x) // Ci verrà mostrato a schermo il valore 1 + +``` + +In questa versione della classe `Point`, `x` e `y` hanno un valore di default uguale a `0`, pertanto non sono necessari argomenti. Nel caso in cui si volesse fornire un valore solamente al membro `y` bisogna necessariamente indicare esplicitamente a quale membro si sta assegnando un valore; questo è dovuto al fatto che il costruttore legge gli argomenti da sinistra a destra. +``` +class Point(var x: Int = 0, var y: Int = 0) +val point2 = new Point(y = 2) +println(point2.y) // Stamperà a schermo 2 +``` + +Questa restrizione aiuta inoltre a migliorare la leggibilità del codice. + +## Membri privati e sintassi per Getter/Setter +Di default i metodi sono pubblici, pertanto non serve anteporre `public`. Se si volesse renderli privati, è necessario anteporre `private` per renderli non accessibili fuori dalla classe in cui sono definiti. +```tut +class Point { + private var _x = 0 + private var _y = 0 + private val bound = 100 + + def x = _x + def x_= (newValue: Int): Unit = { + if (newValue < bound) _x = newValue else printWarning + } + + def y = _y + def y_= (newValue: Int): Unit = { + if (newValue < bound) _y = newValue else printWarning + } + + private def printWarning = println("WARNING: Out of bounds") +} + +val point1 = new Point +point1.x = 99 +point1.y = 101 // prints the warning +``` +In questa versione della classe `Point` le informazoni sono immagazzinate nelle variabili private `_x` e `_y`. Per accedere ai loro valori si possono usare i metodi `def x` e `def y`. I metodi `def x_=` e `def y_=` sono usati per verificare e impostare il valore di `_x` e `_y`. Si ponga attenzione alla sintassi usati per definire i metodi setter: il metodo ha `_=` aggiunto al nome del metodo getter, seguito dai parametri. + +I parametri del costruttore primario indicati con `val` o `var` sono pubblici, ma essendo i valori `val` immutabili, non si potrà utilizzare il codice seguente: +``` +class Point(val x: Int, val y: Int) +val point = new Point(1, 2) +point.x = 3 // <-- Non potrà essere compilato +``` + +Parametri senza `val` o `var` saranno segnati automaticamente come privati, pertanto visibili solo all'interno della classe. +``` +class Point(x: Int, y: Int) +val point = new Point(1, 2) +point.x // <-- Non potrà essere compilato +``` + +## Altre risorse + +* Maggiori informazioni sulle classi sono presenti nel [Libro di Scala](/overviews/scala-book/classes.html) +* Leggi il capitolo [Costruttori ausiliari](/overviews/scala-book/classes-aux-constructors.html) per avere più dettagli.