Usuari:Adriano collantes/Proves

 Introducció

modifica

Swift 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:

  1. fitxer.swift
  2. fitxer.java

Llibreries en Swift

modifica

Qualsevol 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

modifica

A continuació veurem quines clases generiques es fan servir en els 2 llenguatges ambs uns petits matissos.

En tenim de dos classes:

  1. Una variable és un contenidor, el valor del qual pot variar en el transcurs de l'execució del nostre programa.
  2. 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

modifica

Per 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

modifica

Operadors

modifica
Comparadors 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")
}

En Swift existeixen diferents tipus:

  1. El bucle for-in realitza un conjunt de sentències per a cada element d'una seqüència.
  2. El bucle for-in realitza un conjunt de sentències per a cada element d'un array/llista.
  3. 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.
  4. El bucle while mentre avalua el seu estat en l'inici de cada passada.
  5. repeat-while, mentre avalua la seva condició al final de cada pas a través del bucle. Similar a do-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

modifica

Swift 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

modifica

Fem 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

modifica

Depenent 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

modifica
func 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)

modifica

Funcions 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 {

Necessita 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)

modifica

Cada vegada que es defineix una nova classe o estructura, es defineixen de manera efectiva un nou tipus.

Classes i estructures

modifica
struct 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

modifica

Si 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

modifica

Tant 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

modifica

En 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

modifica

Una 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.

enum 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
public enum CompassPoint { North, South, East, West }

Per accedir-hi

CompassPoint directionToHead = CompassPoint.West;
directionToHead.North;

Extensions

modifica

Les 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
modifica

Les 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
modifica

Permeten 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:
modifica
extension 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
modifica

Els 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
modifica

Les 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

modifica

En 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
modifica
public 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
modifica
public 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

modifica

Les 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ó.

Per 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() { ... }

Les 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

modifica
Annotació Ú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ó.

 

Annotació Ú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ó.

  • iOS
  • iOSApplicationExtension
  • OSX
  • OSXApplicationExtension
  • watchOS
  • watchOSApplicationExtension
  • tvOS
  • tvOSApplicationExtension
@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

modifica

Proveeix 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
            }
}
 
Moment de fer un nou "new". Image de http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html

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();
class MyClass {
    public static void main(String[] args) {
        MyClass myFirstObject = new MyClass();
        MyClass mySecondObject = new MyClass();
        myFirstObject = mySecondObject;
        mySecondObject = null;
    }
}

Procés:

  1. Es crea el primer objecte en el heap, es crea la primera referència al stack, i la referència apunta a l'objecte.
  2. Es crea el segon objecte en el heap, es crea la segona referència al stack, i la referència apunta a l'objecte.
  3. 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.
  4. El segon objecte apunta a res.
class MyClass {
    public MyClass myProperty;
    public static void main(String[] args) {
        MyClass myFirstObject = new MyClass();
        myFirstObject.myProperty = new MyClass();
        myFirstObject = null;
    }
}

Procés:

  1. Es crea una MyClass anomenada myProperty en el stack.
  2. Es crea el primer objecte en el heap, es crea la primera referència al stack, i la referència apunta a l'objecte.
  3. 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.
  4. 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

modifica

Els 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:

  1. Es crea una MyClass anomenada myProperty en el stack.
  2. Es crea el primer objecte en el heap, es crea la primera referència al stack, i la referència apunta a l'objecte.
  3. Es crea el segon objecte en el heap, es crea la segona referència al stack, i la referència apunta a l'objecte.
  4. Ara myProperty de la referència myFirstObject apunta cap a l'objecte de mySecondObject.
  5. Ara myProperty de la referència myFirstObject apunta cap a l'objecte de mySecondObject. Recordem que myFirstObject apunta a mySecondObject.
  6. mySeconObject apunta a res.
  7. 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í:

  1. myFirstObject -> Null (stack)
  2. mySecondObject -> Null (stack)
  3. myFirstObject.myProperty -> mySecondObject(heap)
  4. mySecondObject.myProperty -> myFirstObject(heap)

Eines de control

modifica
public 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

modifica

ARC (Automatic Reference Counting)

modifica

Swift 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

modifica

Quan 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
modifica

Partint 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.

 
exemple strong reference
Strong Reference Cycles entre Class Instances
modifica

En 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.

 
Exemple 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
modifica

S’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.

 
exemple weak reference

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.

 
exmple eliminacio strong reference amb weak 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.

 
exmple eliminacio weak reference
Unowned reference
modifica

Les 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.

 
exemple unowned reference

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.

 
exemple eliminació unowned reference

Compilació

modifica

Tant 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

modifica

Si 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

modifica
MacBook-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

modifica
MacBook-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