Usuari:Adriano collantes/Proves
Introducció
modificaSwift es va pensar com un avanç de Objective-C però la keynote d'abans de l'estiu de 2015 es va confirmar una nova versió OpenSource, Swift 2.0 que es la que ocupem en aquest article. Es un llenguatge que es podria dir natiu ja que no en necesita cap entorn o máquina virtual per a poder executar-se (a diferencia de Java), utilitza els propis compilador sota Linux.
Java és, en la majoria dels casos, un llenguatge interpretat. Què vol dir això? Doncs que un programa especialitzat, l'intèrpret de Java, ha d'anar llegint el codi del programa instrucció a instrucció per descobrir quin és la propera acció a realitzar. Aquesta operació costa molts més cicles de CPU que executar un programa en codi màquina natiu, ja que en aquest últim cas és el propi microprocessador el que s'encarrega de decodificar les instruccions a nivell màquina.
Programes escrits en el llenguatge Java poden executar-se igualment en qualsevol tipus de maquinari. Est és el significat de ser capaç d'escriure un programa una vegada i que pugui executar-se en qualsevol dispositiu, tal com resa l'axioma de Java, "write once, run anywhere".
Per a això, es compila el codi font escrit en llenguatge Java, per generar un codi conegut com “bytecode” (específicament Java bytecode)—instruccions màquina simplificades específiques de la plataforma Java. Aquesta peça està “a mig camí” entre el codi font i el codi màquina que entén la dispositiva destinació. El *bytecode és executat llavors en la màquina virtual (*JVM), un programa escrit en codi natiu de la plataforma destino (que és el que entén el seu maquinari), que interpreta i executa el codi. A més, se subministren biblioteques addicionals per accedir a les característiques de cada dispositiu (com els gràfics, execució mitjançant brins o *threads, la interfície de xarxa) de forma unificada. S'ha de tenir present que, encara que hi ha una etapa explícita de compilació, el bytecode generat és interpretat o convertit a instruccions màquina del codi natiu pel compilador JIT.
Extensions:
- fitxer.swift
- fitxer.java
Llibreries en Swift
modificaQualsevol framework de Objective-C o C que suporta mòduls es poden importar directament en Swift. Això inclou tots els sistemes de frameworks de Objective-C com a Fundació, UIKit i SpriteKit-així com biblioteques de C comuns subministrats amb el sistema. Per exemple, per utilitzar les API de Foundation a partir d'un arxiu de Swift, afegiu la següent sentència import al principi de l'arxiu:
//Swift
import Foundation
Amb aquesta declaració d'importació, aquest arxiu Swift ara pot accedir a totes les classes, els protocols, mètodes, propietats i constants. Podem trobar totes les llibreries a la següent direcció:
http://www.swifttoolbox.io/
Llibreries en Java
modifica//Java
import java.util.*; //inclou tots els paquets java.util
Tot el que no hi es en el paquet java.lang o el paquet local ha de ser importat. Podem trobar totes les llibreries a la següent direcció:
http://docs.oracle.com/javase/7/docs/api/
Variables
modificaA continuació veurem quines clases generiques es fan servir en els 2 llenguatges ambs uns petits matissos.
Tipus
modificaEn tenim de dos classes:
- Una variable és un contenidor, el valor del qual pot variar en el transcurs de l'execució del nostre programa.
- Una constant, per contra, és un valor que romandrà immutable durant el mateix.
Tipus | Valor |
---|---|
Int | rang des de -2.147.483.648 i 2,147,483,647. |
Float | número decimal de 32 bits fins a 6 decimals de precisió. |
Double | coma flotant de 64 bits fins a 15 decimals de precisió. |
Bool | binari 0 (false) o 1 (true). |
String | array de caracters. |
Char | Character en Swift. |
És molt important recordar que les variables a diferencia de JAVA sempre han d'inicialitzar-se amb un valor:
//Swift
let feina = "DAMO"
let feina: String = "DAMO"
var feina; //Error no existeix valor buit.
var feina: String = "DAMO"
print(feina)
//Java
String feina;
final String feina = "DAMO"; //constant
System.out.println (feina)
En Swift no fa falta definir el tipus de la variable perquè el compilador te la propietat de determinar per nosaltres quin és el tipus de dada a usar en una variable o constant en funció del seu contingut. Però no poden deixar-se varibles buides o sense valor assignat, doncs el valor buit no existeix com a tal. Podem cadenes lògiques de Strings:
//Swift
var nom = "Hola", cognom = "Todos"
var nombreCompleto : String { return nom + " " + cognom }
var nombreCompleto : String = "nom" + " " + "cognom"
//Java
String nombre = nom + " " + cognom;
Opcionals
modificaPer defecte Swift no admet valors buits d'inicialització, però sí podem inicialitzar una variable sense saber què valor tindrà en aquest moment, si no que s'establirà en el futur. Això es fa amb un ‘?’ després del tipus de variable.
//Swift
var feina: String? = "DAMO"
print(feina!)
//Resultat: DAMO
//Java no té opcionals
La interrogació indica que la variable és d’un cert tipus, però que encara no volem o no podem assignar-li un valor, per la qual cosa se li assignarà automàticament un valor nul i s'emmagatzemarà en un contenidor específic. Quan vulguem recuperar el valor cal afegir el modificador ‘!' perquè extregui d'aquest contenidor opcional el valor i ho mostri tal qual. És el que es diu un unwrap o extreure d'un contenidor opcional un valor que podria o no existir al moment que es pregunta per ell. En cas de no ficar-ho et retornarà una cadena semblant a la següent:
print(feina)
//Resultat: Optional("DAMO")
Això passa perque intentes obtenir el valor d'un opcional tractant-lo com una variable quant no es així, per tant, la resposta es clara, sóc un Optional que tinc com a valor una cadena "DAMO", per tant, sóc un String.
Controls de flux
modificaOperadors
modificaComparadors | Operadors |
---|---|
a == b | NOT: !a
|
a != b | AND: a && b
|
a > b | OR: a || b
|
a < b | |
a >= b | |
a <= b |
Condicionals
modifica//Swift
if valid { /*cert*/} else{ /*fals*/ }
//Java
if (valid) { /*cert*/ }else{ /*fals*/ }
//Swift
switch valid { case 1:/*cert*/ default: /*defecte*/ }
//Java
switch (valid) { case 1:/*cert*/ default: /*defecte*/ }
La diferencia principal entre totes les setencies es que Switch no fa servir parentesis en cap moment, només quan necessita comparar diversos elements amb operadors lógics:
if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword {
print("Welcome!")
} else {
print("ACCESS DENIED")
}
Bucles
modificaEn Swift existeixen diferents tipus:
- El bucle for-in realitza un conjunt de sentències per a cada element d'una seqüència.
- El bucle for-in realitza un conjunt de sentències per a cada element d'un array/llista.
- El bucle for realitza una sèrie de declaracions fins que es compleixi una condició específica, típicament incrementant un comptador cada vegada que el bucle acaba.
- El bucle while mentre avalua el seu estat en l'inici de cada passada.
repeat
-while
, mentre avalua la seva condició al final de cada pas a través del bucle. Similar ado
-while
var llista = [1,2,3,4,5];
for index in 1...5 {
print("\(index) times 5 is \(index * 5)")
}
for index in llista {
print("\(index) times 5 is \(index * 5)")
}
for var index = 0; index < 5; ++index {
print("\(index) times 5 is \(index * 5)")
}
repeat {
statements
} while condition
while condition {
statements
}
A continuació veiem com és a Java:
while (expresio) {setencia}
for (index; condicio; index++/index--){sentencia}
for(Demarcacion d: Demarcacion.values()){
System.out.println(d.toString()+" - ");
}
Propi dels opcionals
modifica//Swift
var num: Int?
if let roomCount = num {
print("John's residence has \(roomCount) room(s).")
} else {
print("Unable to retrieve the number of rooms.")
}
//¿Correcte?
En Swift quan fem una sentencia if..else.. podem definir si alhora de comparar el valor se li assigna a una variable nova. Així podem comprovar si es una variable nula o no i alhora reutilitzarla. En l'exemple anterior podem veure clarament que num conté un valor buit, per tant, en la sentencia s'anirà al else.
Mètodes
modificaSwift integra la característica anomenada String Interpolation que és una manera de crear un nou valor String barrejant variables i qualsevol expressió. Les variables deuen ser precedides per una diagonal invertida i envoltada per parèntesi.
Pots realitzar qualsevol barrejade tipus de variables, amb la qual Apple pretén facilitar l'escriptura i concatenació d'expressions a tipus String i que requeria un major esforç en Objective-C.
var twitterProfileUrl : String { return "https://twitter.com/\(twitterUser)" }
Veiem dos codis que fan el mateix:
public func sayHello(personName: String) -> String {
let greeting = "Hello, " + personName + "!"
return greeting
}
public String sayHello(String personName){
String greeting = "Hello, " + personName + "!";
return greeting;
}
Diferència
modificaFem una mica d'anàlisi del que es cada element:
Tipus | Arguments | Retorn | ||
---|---|---|---|---|
Swift | func | public | personame: String | String |
Java | - | public | String personName | String |
Tip: func nomès diu al compilar que es tractar d'una funció. Tot retorn en Swift va precedit de "->"
Modificadors
modificaDepenent el nivell de control que es vol oferir a la nostra colecció.
Modificador | Classe | Package | Subclasse | Tots |
---|---|---|---|---|
public | Si | Si | Si | Si |
protected | SI | Si | Si | No |
private | Si | Si | No | No |
sense especificar | Si | No | No | No |
En comptes de "protected" Swift implementa "internal".
Múltiples retorns
modificafunc minMax(array: [Int]) -> (min: Int, max: Int) {
var currentMin = array[0]
var currentMax = array[0]
for value in array[1..<array.count] {
if value < currentMin {
currentMin = value
} else if value > currentMax {
currentMax = value
}
}
return (currentMin, currentMax)
}
Tip: En java NOMÉS es pot retornar 1 variable. Per accedir a les variables tractarem la funció com un objecte:
let bounds = minMax([8, -6, 2, 109, 3, 71])
print("min is \(bounds.min) and max is \(bounds.max)")
//Renombrar mètodes
var mi_algoritmo: ([Int]) -> (min: Int, max: Int) = minMax
print("min is \(mi_algoritmo([8, -6, 2, 109, 3, 71]).min) and max is \(mi_algoritmo([8, -6, 2, 109, 3, 71]).max)")
Funcions niades (Anònimas)
modificaSwift
modificaFuncions niades estan ocults del món exterior per defecte, però tot i així es poden cridar i utilitzats per la seva funció de tancament. Una funció envoltant també pot retornar una de les seves funcions niats per permetre la funció niada per ser utilitzat en un altre àmbit d'aplicació.
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
func stepForward(input: Int) -> Int { return input + 1 }
func stepBackward(input: Int) -> Int { return input - 1 }
return backwards ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(currentValue > 0)
Tip: Depenent de la condició backwards agafarà un dels Int retornat per una de les dues funcions i serà un Int el que retornarà la funció principal. Per tant, l'estructura:
func nom_funcion(arguments: Tipus, ...) -> (Tipus_niades_diferents, ...) -> Tipus_principal {
Java
modificaNecessita fer servir classes internes.
public class Outer {
static private int CountStatic = 0;
int CountNonStatic = 0;
public static class Inner {
public void doInner() {
System.out.println( CountStatic );
}
}
}
POO (Programació Orientada a Objectes)
modificaCada vegada que es defineix una nova classe o estructura, es defineixen de manera efectiva un nou tipus.
Classes i estructures
modificastruct Resolution {
var width = 0
var height = 0
}
class VideoMode {
var resolution = Resolution()
var interlaced = false
var frameRate = 0.0
var name: String?
}
//Recordem a variables quina es la diferencia entre tots dos en ús.
Tip per Swift: Defineix noms perquè coincideixi amb la capitalització dels tipus Swift estàndard (com String, Int i Bool) per a diferenciar-les de variables o mètodes.
Tip per Java: No existeix struct!
- Les estructures són tipus de valor, mentre que les classes són tipus de referència.
- A diferència de les classes, es poden crear instàncies de les estructures sense utilitzar un operador new.
- Les estructures poden declarar constructors, però han d'utilitzar paràmetres.
- Una estructura no pot heretar d'una altra estructura o classe, ni pot ser la base d'una classe.
- Una estructura pot implementar interfícies.
//Swift
let someResolution = Resolution()
let someVideoMode = VideoMode()
//Java
VideoMode someVideoMode = new VideoMode()
Estructures i classes utilitzen la sintaxi de inicialitzador per a noves instàncies. La forma més simple de la sintaxi d'inicialització utilitza el nom del tipus de la classe o estructura, seguit de parèntesi buits, com Resolution() o VideoMode(). Això crea una nova instància de la classe o estructura, amb propietats inicialitzats als valors per defecte. Agafem el struct del primer exemple, podem accedir-hi als seus valors sempre i quan no siguin private:
//incializatció
let vga = Resolution(width: 640, height: 480)
//java
Resolution vga = new Resolution(640,480);
Tip per Swift:¿Es pot comparar classes pròpies amb els comparadors coneguts?
No. Per això hi ha uns comparadors especifics.
- Identical to (
===
) vol dir que dues constants o variables de tipus de classe es refereixen exactament a la mateixa instància de classe. - Not identical to (
!==
) vol dir que dos casos són considerats "igual" o "equivalent" al valor, per algun significat apropiat de "igual", segons el definit pel dissenyador del tipus.
Tip per java: Has de crear el mètode de comparació.
En Swift, molts tipus de dades bàsiques com String, Array, i el Diccionari s'implementen com estructures. En aquest cas es copien les dades, com ara cadenes, matrius i diccionaris quan s'assignen a una nova constant o variable, o quan es passen a una funció o mètode.
Constructor de classes
modificaSi volem definir constructors de classe propis:
init(arguments){} //Swift
nomclass(arguments){} //Java
Per defecte tant un com l'altre llenguatge tenen un constructor per defecte.
Accedir a atributs
modificaTant Java com Swift per accedir a atributs "public" (que no siguin private) es fa de la mateixa manera:
someResolution.width
someVideoMode.resolution.width
Herència
modificaEn Swift podem fer servir inicialitzador de conveniència. Podem crear nous tipus de inicializadors que ens permetin rebre altres paràmetres diferents que els que la classe requereix de per si, i que ens permetin construir més còmodament la instància.
struct valoresVitales {
var fuerza: Int
var vida: Int
}
class Enemigo {
let nombre: String
let vital: valoresVitales
init(nombre: String, vital: valoresVitales) {
self.nombre = nombre
self.vital = vital
}
}
class Orco: Enemigo {
let clan: String
init(nombre: String, vital: valoresVitales, clan: String) {
self.clan = clan
super.init(nombre: nombre, vital: vital)
}
convenience init (nombre: String, fuerza:Int, vida:Int, clan:String) {
let vitalOrco = valoresVitales(fuerza: fuerza, vida: vida)
self.init (nombre: nombre, vital: vitalOrco, clan: clan)
}
}
//Codi agafat de https://applecoding.com
Un exemple clar on un objecte Orco hereta de la classe Enemigo i apart es fa una extensió de la classe Orco afegint clan. En temps d'execució pots fer una extensió d'una classe, per exemple, que possi la valia del Orco:
extension Enemigo {
var valia: Int {
return (self.vital.fuerza * self.vital.vida)
}
}
//Codi agafat de https://applecoding.com
Senzillament definim una extensió de Enemic, amb una nova propietat calculada. Una propietat que recupera el valor de força i vida dels valors propis de la classe (self) i torna la multiplicació d'aquests valors. La instancia que existeixi de Orco si accedeix a Orco.valia li retornara el valor de la nova propietat.
Enumerations
modificaUna enumeració defineix un tipus comú d'un grup de valors relacionats i li permet treballar amb aquests valors en una forma de tipus segur dins del seu codi.
Swift
modificaenum CompassPoint {
case North
case South
case East
case West
}
Per accedir-hi:
var directionToHead = CompassPoint.West
//pots accedir-hi més tard amb un punt perque ya te el punter sobre CompassPoint
directionToHead = .North
Java
modificapublic enum CompassPoint { North, South, East, West }
Per accedir-hi
CompassPoint directionToHead = CompassPoint.West;
directionToHead.North;
Extensions
modificaSwift
modificaLes extensions permeten afegir funcionalitats a una class, estructura, enumeració o protocol. Això permet tenir accés a extend types als quals no es té accés al codi font original.
Les extensions de Swift permeten:
- Afegir propietats computades i propietats de tipus computades
- Definir instancies de mètodes i tipus de mètodes
- Proporcionar nous incialitzadors
- Definir subscripts
- Definir i utilitzar tipus niats (“anidats”)
- Convertir un tipus existent a un protocol
Les extensions poden estendre un tipus per i fer que adopti un o més protocols. En cas de voler indicar diversos protocols, la sintaxi seria la següent:
extension SomeType: SomeProtocol, AnotherProtocol {
// implementation of protocol requirements goes here
}
Nota: Si es deifineix una extensió per afegir una nova funcionalitat a un type existent, la nvoa funcionalitat estarà disponible per totes les intàncies d’aquell type, tot i qeu hagin estat prèviament creades.
Propietats computades
modificaLes extensions poden afegir propietats computed instance i propietats computed type a tipus existents. En aquest exemple s’afegeixen 5 propietats computed instance al tipus Double, per tal d’afegir suport per treballar amb unitats de distancia.
extension Double {
var km: Double { return self * 1_000.0 }
var m: Double { return self }
var cm: Double { return self / 100.0 }
var mm: Double { return self / 1_000.0 }
var ft: Double { return self / 3.28084 }
}
let oneInch = 25.4.mm
print("One inch is \(oneInch) meters")
// prints "One inch is 0.0254 meters"
let threeFeet = 3.ft
print("Three feet is \(threeFeet) meters")
// prints "Three feet is 0.914399970739201 meters"
Incialitzadors
modificaPermeten estendre altres tipus els teus propis tipus com a paràmetres d’inicialització a acceptar les pròpies inicialitzacions o afegir inicialitzacions diferents. Es poden afegir nous incialitzadors a una classe, però mai es pot “sobreescriure” l’inicialitzador o el desinialitazdor per defecte de la classe.
extension Rect {
init(center: Point, size: Size) {
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
self.init(origin: Point(x: originX, y: originY), size: size)
}
}
Mètodes:
modificaextension Int {
func repetitions(task: () -> Void) {
for _ in 0..<self {
task()
}}}
//Result
3.repetitions({
print("Hello!")
})
// Hello!
// Hello!
// Hello!
El mètode repetitions(_:) agafa un argument de tipus void (sense paràmetres) i que tampoc retorna cap valor. Després d’afegir aquest mètode es pot cridar repetitions(_:)a qualsevol integer perquè faci una tasca n vegades.
Mutació o modificació de mètodes instance
modificaEls mètodes afegits amb una extensió poden modificar. Les estructures i mètodes d’enumeració que modifiquen self o les seves propietats han de marcar la instància com a mutating, tal i com fan els , mètodes mutating a la implementació original
El següent exemple afegeix una mutació anomenada square al tipus int que calcula el quadrat del valor original.
extension Int {
mutating func square() {
self = self * self
}
}
var someInt = 3
someInt.square()
// someInt is now 9
Subscripts
modificaLes extensions poden afegir nous subscripts a un tipus existent.
extension Int {
subscript(var digitIndex: Int) -> Int {
var decimalBase = 1
while digitIndex > 0 {
decimalBase *= 10
--digitIndex
}
return (self / decimalBase) % 10
}
}
746381295[0]
// returns 5
746381295[1]
// returns 9
746381295[2]
// returns 2
746381295[8]
// returns 7
Tipus niats (“anidats”)
modifica
Les extensions poden afegir tipus niats a les classes, estructures i enumeracions diferents.
extension Int {
enum Kind {
case Negative, Zero, Positive
}
var kind: Kind {
switch self {
case 0:
return .Zero
case let x where x > 0:
return .Positive
default:
return .Negative
}}}
Herència Java
modificaEn Java, la classe que deriva d’una altra classe és amoneda subclass o classe filla, mentre que la original és amoneda superclass o classe pare.
A diferencia de Swift, si es vol modificar el comportament de la classe pare, s’ha de crear una subclass que derivi de la classe pare. D’aquesta forma es poden utilitzar els camps i mètodes (a excepció de la constructora i desctructora) de la classe pare, fent una especialització concreta.
Exemple d’herència
Clase pare
modificapublic class Bicycle {
// the Bicycle class has three fields
public int cadence;
public int gear;
public int speed;
// the Bicycle class has one constructor
public Bicycle(int startCadence, int startSpeed, int startGear) {
gear = startGear;
cadence = startCadence;
speed = startSpeed;
}
// the Bicycle class has four methods
public void setCadence(int newValue) {
cadence = newValue;
}
public void setGear(int newValue) {
gear = newValue;
}
public void applyBrake(int decrement) {
speed -= decrement;
}
public void speedUp(int increment) {
speed += increment;
}
}
Classe filla
modificapublic class MountainBike extends Bicycle {
// the MountainBike subclass adds one field
public int seatHeight;
// the MountainBike subclass has one constructor
public MountainBike(int startHeight,
int startCadence,
int startSpeed,
int startGear) {
super(startCadence, startSpeed, startGear);
seatHeight = startHeight;
}
// the MountainBike subclass adds one method
public void setHeight(int newValue) {
seatHeight = newValue;
}
}
El que et permet fer una subclass és heretar els membres i mètodes de la classe pare, reemplaçar-los i/o complimentar-los.
Atributs o Anotacions
modificaLes anotacions són metadata d’un programa que no tenen cap efecte directa o operen sobre el codi, només serveixen per fer anotacions. Els seus possible susos sóns els següents:
Funcions
modifica- Informar al compilador: Les anotacions poden ser utilitzades pel compilador per detectar errors o evitar warnings.
- Compile-time and deployment-time processin: Les eines software poden processar la informació de les anotacions per generar codi, com per exemple fitxers XML.
- Processament en temps d’execució: Algunes anotacions permeten ser utilitzades en temps d’execució.
Format
modificaPer especificar una anotació, s’ha de posar el caràcter ‘@’. Això indica al compilador que és una anotació. Les anotacions poden incloure elements, que poden tenir nom o no, i els seus corresponents valors:
@Author(
name = "Benjamin Franklin",
date = "3/27/2003"
)
class MyClass() { ... }
Usos
modificaLes anotacions es poden utilitzar en les declaracions de classes, camps, mètodes i altres elements dels programes. Des de la versió de Java SE 8 les anotacions també poden ser aplicades a l’ús de tipus. A continuació alguns exemples:
//Class instance creation expression:
new @Interned MyObject();
//Type cast:
myString = (@NonNull String) str;
implements clause:
class UnmodifiableList<T> implements
@Readonly List<@Readonly T> { ... }
//Thrown exception declaration:
void monitorTemperature() throws
@Critical TemperatureException { ... }
Exemples d'anotacions
modificaJava
modificaAnnotació | Ús |
---|---|
@Deprecated | Indica que l’element està desfasat i que no s’hauria d’utilitzar. El compilador genera un warning quan s’utilitza el mètode marcat. |
@Override | Informa al compilador que l’element sobreescriurà l’element declarat a la superclass. |
@SuppressWarnings | Indica al compilador que no mostri alguns warnings específics que poden ser generats, com per exemple al utilitzar un mètode deprecated. |
@SafeVarargs | Quan s’aplica a un mètode o constructor, assegura que el codi no farà cap operació insegura en els vargargs que passa com a paràmetre. Quan s’utilitza aquesta anotació, no es mostren els warnings que estan relacionats amb els varargs. |
Anotacions que s’apliquen a altres anotacions. Les més interessants són: | |
@Documented | Indica que en els elements que s’utilitzi l’anotació seran documentats utilitzant l’eina Javadoc tool. |
@Target | Restringeix quins tipus d’elements s’aplica l’anotació. |
Swift
modificaAnnotació | Ús |
---|---|
@Available | Aquest atribut s’aplica a qualsevol declaració per indicar el cicle de vida relatiu a certes plataformes i versions de sistema operatiu.
Es pot indicar com una llista, de dos o més arguments separats per coma o bé utilitzar l’asterisc (*) oer indicar que està disponible per totes les plataformes que es llisten a continuació.
|
@Unavailable | La declaració no està disponible per les plataforma especificades |
@Introduced | indica a partir de quina versió de la plataforma especificada la declaració va ser introduïda |
@Deprecated | indica la primera versió de la plataforma especificada en que la declaració està desfasada. |
@Obsoleted | Indica la primera versió de la plataforma especificada en que la declaració és obsoleta. Quan una declaració és obsoleta s’elimina de la plataforma i ja no pot ser utilitzada. |
@Message | Servei per mostrar un missatge textual que es mostra al fer la compilació o per alertar d’un error de l’ús d’una declaració que està obsoleta o desfasada. El missatge és un string. |
@Renamed | S’utilitza per mostrar un missatge textual que indica el nou nom d’una declaración que ha estat renombrada. El nou nom es mostra al compilador quan s’emet un error per el canvi de nom de la declaració. El nou nom es un string. |
@testable | Aplicar aquest atribut per importar les declaracions de mòduls compilats amb el la opció de test activat, de mode que es pot accedir a qualsevol entitat marcada amb nivell de modificació intern, tal i com si haguessin estat declats com a nivell de modificació públic. |
@warn_unused_result | S'utilitza perque el compilador emeti un warning quan el mètode o funció és cridat sense utilitzar el seu resultat. |
Gestió de memoria
modificaJava
modificaProveeix una solució automàtica a la gestió de memòria. En la majoria dels casos el procés d'alliberar memòria ha de pertànyer a la lògica de les aplicacions. Això és típic per a la memòria que ha estat usada per a crear apilaments (piles - heap) en Java, aquests casos es pot veure en constants per gestió de pools i en les àrees dels mètodes. La pila (heap) és una part de la memòria on els objectes de Java viuen, i aquesta és l'única part de la memòria que és d'alguna manera involucrats en el procés de recol·lecció del garbage collector. Tot el garbage collector gira entorn a assegurar que la pila (heap) de memòria sempre estigui alliberant tant espai com sigui possible. El propòsit del garbage collector és trobar i eliminar objectes que no es puguin assolir.
Està a càrrec de la JVM (Java Virtual Machine), l'experiència indica que quan els programes fan una petició al garbage collector, la JVM sol concedir aquesta petició a ser atesa en una manera primerenca, però no es garantia que això es compleixi . En general es diu que el Garbage Collector, pensa per si sol i s'executa quan ell ho desitja.
Cada programa fet en Java té un o més fils, on cada un d'aquests és propietari de la seva part a la pila de la memòria. Un objecte és elegible pel garbage collector, quan no es pugui accedir-hi (a través del seu fil), això és que no té una variable de referència accessible que apunti a l'objecte en qüestió. El garbage collector no pot assegurar que sempre hi hagi prou memòria, només que la memòria que hi es serà gestionada el més eficientment possible.
class MyClass {
public static void main(String[] args) {
MyClass myObject;
myObject = new MyClass(); //Primer objecte
myObject = new MyClass(); //Segon objecte
}
}
Tip: Només s'assigna el primer ja que 1 punter no pot apuntar a 2 llocs diferents.
És un procés de baixa prioritat, pel que no es passa en tot moment alliberant memòria, sinó que passa de tant en tant, que podria ser en un temps mort del processador, encara que també nosaltres podríem suggerir-li que passi, però passarà quan pugui i vulgui, un parell d'exemples de com enviar cridar son aquests:
System.gc();
/* o */
Runtime.getRuntime().gc();
Cas 1
modificaclass MyClass {
public static void main(String[] args) {
MyClass myFirstObject = new MyClass();
MyClass mySecondObject = new MyClass();
myFirstObject = mySecondObject;
mySecondObject = null;
}
}
Procés:
- Es crea el primer objecte en el heap, es crea la primera referència al stack, i la referència apunta a l'objecte.
- Es crea el segon objecte en el heap, es crea la segona referència al stack, i la referència apunta a l'objecte.
- La primera referència apunta cap al segon objecte. En aquest moment el primer objecte es queda sense referència, és rebutjat pel GC, i s'allibera memoria.
- El segon objecte apunta a res.
Cas 2
modificaclass MyClass {
public MyClass myProperty;
public static void main(String[] args) {
MyClass myFirstObject = new MyClass();
myFirstObject.myProperty = new MyClass();
myFirstObject = null;
}
}
Procés:
- Es crea una MyClass anomenada myProperty en el stack.
- Es crea el primer objecte en el heap, es crea la primera referència al stack, i la referència apunta a l'objecte.
- Es crea el segon objecte en el heap, es crea la segona referència al stack, i la referència apunta a l'objects, com a atribut.
- La primera referència apunta a res. En aquest moment el primer objecte es queda sense referència, és rebutjat pel GC, i s'allibera memoria. Per tant alhora es buida tota propietat.
No en quedaría cap element en el heap.
Island of Isolation
modificaEls objectes tenen referències cap a ells, però no són accessibles aquests objectes per al programador, és a dir, no tenim referències dels objectes, i queden aïllats per al seu ús.
class MyClass {
public MyClass myProperty;
public static void main(String[] args) {
MyClass myFirstObject = new MyClass();
MyClass mySecondObject = new MyClass();
myFirstObject.myProperty = mySecondObject;
mySecondObject.myProperty = myFirstObject;
mySecondObject = null;
myFirstObject = null;
}
}
Procés:
- Es crea una MyClass anomenada myProperty en el stack.
- Es crea el primer objecte en el heap, es crea la primera referència al stack, i la referència apunta a l'objecte.
- Es crea el segon objecte en el heap, es crea la segona referència al stack, i la referència apunta a l'objecte.
- Ara myProperty de la referència myFirstObject apunta cap a l'objecte de mySecondObject.
- Ara myProperty de la referència myFirstObject apunta cap a l'objecte de mySecondObject. Recordem que myFirstObject apunta a mySecondObject.
- mySeconObject apunta a res.
- myFirstObject apunta a res.
¿Quin problema hi ha? Que ara els punters originals no apunten a res i no hi ha referencies al stack. No hi ha una mínima connexió amb les referències del stack, quan un objecte no té encara que sigui una referència indirecta amb el stack, és candidat perquè el GarbageCollector l'elimini en el seu següent passat.
Per tant quedaria així:
- myFirstObject -> Null (stack)
- mySecondObject -> Null (stack)
- myFirstObject.myProperty -> mySecondObject(heap)
- mySecondObject.myProperty -> myFirstObject(heap)
Eines de control
modificapublic class MyClass {
String id;
protected void finalize(){
System.out.println(this.id); //id atribut de la class referenciada.
}
/* Tractament d'alguns dels casos anteriors.
*/
}
Avans de executar-se el GarbageColler per esborrar del heap el objecte executa finalize(), per poder veure quins objectes toca esborrar.
Swift
modificaARC (Automatic Reference Counting)
modificaSwift utilitza un mecanisme automàtic anomenat (ARC) que fa un seguiment i gestiona l´ús de memòria de l’aplicació. En la majoria dels casos, no cal preocupar-se per la gestió de memòria, doncs l’ARC la allibera automàticament la memòria utilitzada per una instància d’una classe quan ja no es necessita.
De totes formes, en alguns casos l’ARC necessita informació sobre la relació entre diferents parts del teu codi, per tal de poder fer la gestió automàticament. A continuació es descriuen aquests casos i es mostra com habilitar l’ARC perquè faci la gestió automàtica.
Nota: El conteig de referencies només s’aplica a les classees. Les estructures i les enumeracions són de tipus valor i no tipus referencia, i no son emmagatzemades i passades per referencia.
Funcionament de l’ARC
modificaQuan es crea una nova instancia duna classe l’ARC reserva un chunk de memòria per emmagatzemar ,aquesta instància. Aquest espai de moria guarda informació sobre el tipus d’instància i els valors que emmagatzemen les propietats d’aquesta. En el moment en que la instància ja no es necessita, l’ARC allibera la memòria. Si s’intentés accedir a una instància que l’ARC ja ha eliminat, l’aplicació donarà error.
Perquè això no passi, es fa un seguiment de quantes propietats, constants i variables fan referencia a la instancia en qüestió, l’ARC no alliberarà l’espai utilitzat per la instancia mentre hi hagi alguna referencia cap aquella instancia.
Per aquest motiu, quan s’assigna una instancia duna classe a una propietat, constant o variable, es crea una strong reference cap aquella instancia. El lligam es diu que és fort, degut a que mentres existeixi la referencia, la instancia no s’eliminarà.
Creació d'Strong reference
modificaPartint d’aquesta clase
class Person {
let name: String
init(name: String) {
self.name = name
print("\(name) is being initialized")
}
deinit {
print("\(name) is being deinitialized")
}}
Si fem:
var reference1: Person?
La variable reference1 apunta nil. Pero si fem:
reference1 = Person(name: "John Appleseed")
// prints "John Appleseed is being initialized"
Es crea una strong reference entre reference 1 i la instancia de Person. Com que hi ha almenys una strong reference, l’ARC s’assegura que aquesta instancia de Person es mantingui en memoria. Es poden crear tantes strong reference cap a la mateixa instancia com es vulgui.
reference2 = reference1
reference3 = reference1
Mentres que la instancia de Person tingui algun strong reference, no s’eliminara excepte si fem que totes apuntin a nil.
reference3 = nil
// prints "John Appleseed is being deinitialized"
Finalment s’eliminaria l'strong reference.
Strong Reference Cycles entre Class Instances
modificaEn els exemples anteriors l’ARC és capaç de fer un seguiment del nombre de referencies de la instancia Person, però és possible escriure un codi en el que una instancia d’una class mai arribi a tenir zero referencies. Això pot passar quan dues instancies de classes tenen una strong reference entre elles, de mode que es mantenen vives mútuament. Aquest fet es coneix com a strong reference cycle.
L’Strong reference cycle es pot resoldre declarant les referencies com a weak or unowned en comptes d’strong references.
Weak References
modificaS’ha d’utilitzar aquest tipus de referencia per evitar els reference cycles sempre que sigui possible que hi hagi una referencia sense valor en algun moment de la vida de l’objecte.
A l'exemple de la imatge, selimina la referencia de john a la instància de persona, per tan ja no hi ha cap strong reference.
En aquest cas, també s'elimina la strong reference de unit4A cap a la instància de Apartment, i com que Apartment té una weak reference sobre la instància de Person, s'eliminen les dues instàncies.
Unowned reference
modificaLes unowned references no creen un strong hold a la instancia que es refereixen, però s’assumeix que sempre tindrà un valor, i per tant no es un tipus opcional.
En cas d'eliminar la strong reference de john cap a la instància de Customer, com que no queda cap strong reference cap a la instància i la de credit car no pot estar buida, s'eliminen les dues instàncies.
Compilació
modificaTant Swift como Java son llenguatges que es poden fer sota terminal, però, per comoditat es fan servir entorns como Xcode per Swift, Eclipse, NetBeans per a Java.
Proves des de Terminal en Swift
modificaSi l'entorn es correcte i els softlinks s'han generat correctament al sistema Unix des de terminal s'hauri veure així o similar:
MacBook-Air-de-Adriano:~ adrianocollantes$ swift
Welcome to Apple Swift version 2.1 (700.1.101.6 700.1.76). Type :help for assistance.
1>
Aquest és l'interpret de Swift sota Terminal. Per sortir:
:exit
Compilació des de Terminal en Swift
modificaMacBook-Air-de-Adriano:~ adrianocollantes$ swift fitxer.swift
Tip: Si el fitxer no existeix no en crea cap, et dóna error.
Compilació des de Terminal en Java
modificaMacBook-Air-de-Adriano:~ adrianocollantes$ javac HelloWorld.java
MacBook-Air-de-Adriano:~ adrianocollantes$ java -jar HelloWorld.jar
Entorns externs (exemples)
modifica- Xcode -> Swift (com a IDE), Java (no compila)
- NetBeans -> Java
- Eclipse -> Java