10 noiembrie 2022

Maven class - ziua 1

Introducere

Build tool --> produce un artifact

Maven is built with Maven :)

ANT - construit ca alternativă la Make - nu este rival Maven, se pot folosi împreună


mvn versions:update-properties  - face update la toate dependințele din pom cu ultimele lor versiuni publicate


<build>

  <finalName> GEO </finalName>   <!-- app se va numi GEO.jar -->

  <plugins>

    <plugin>

          ...

    </plugin>

  </plugins>

</build>


> mvn compile --> .class files

> mvn package --> .jar files


Structura Maven

- Maven se uită prestabilit în src/main/java

- compilează in /target

- pom.xml: project info (groupId, artifactId, version, packaging (jar/war)), dependencies (same info), goals, etc

Goals

  • clean
  • compile
  • package (rulează deja compile)
  • install (ruleaza package și instalează jar/war în local repository)
  • deploy (rulează install și copiază rezultatul într-un repo remote)


Maven storage prestabilit: ~/.m2/repository


Dependencies

Dependency: specificare groupId, artifactId, version

SNAPSHOT este versiunea inițială a proiectului în dezvoltare

  - se pot folosi si sufixele M1 (milestone1) sau RC1 (release candidate1) când urmează să fie lansat

  - sufixe RELEASE sau FINAL pt proiectul final


Tipuri de packaging: pom, jar, war, ear, maven-plugin; toate sunt arhive zip la bază; tipul prestabilit este jar

Diferențe între jar, war și ear:

  • create pentru medii diferite
  • la nivel intern: ear trebuie să aibă un META-INF/application.xml , un war cere un WEB-INF/web.xml , iar un jar nu are astfel de cerințe

Pentru tipul de packaging pom: toate dependințele sunt descărcate în arhivă


Dependințe tranzitive: dependințe descărcate automat, de care depind dependințele declarate în proiect


Scope:

  • compile - prestabilit, dependința este disponibilă oriunde în aplicație, propagată în proiectele dependente (tranzitivă)
  • provided - la fel ca compile, dar dependința nu va fi inclusă în artifactul final; disponibilă doar la momentul compilării. Nu este tranzitivă
  • runtime - este nevoie de ea doar la execuție 
  • test (ex. junit)
  • system - deprecated, a nu se folosi! - pt a specifica direct un jar anume din sistem
  • import (...)

27 octombrie 2022

Kotlin - colecții - ziua 7

Colecții

var people: List<Pers?> = listOf(Pers(23), null)
for (person: Pers? in people) {
println(person?.age)
}

val items = IntArray(2)
items[0] = 1
items[1] = 2

val numbers = intArrayOf(1,2,3,4,5)
numbers.forEachIndexed {index, element ->
println("$index is $element")
}


High order functions

= o funcție care ia ca parametru o altă funcție

val action = { println("Hello World") }
// val calc = {x:Int, y:Int -> x*y}
val calc: (Int, Int) -> Int = {x, y -> x*y}
doSomething(action)

fun doSomething(func: () -> Unit) {
func()
}


Inlining 

- ajută la performanță

val ints = listOf(1,2,3,4)
val i = first(ints, { i -> i == 3})
println(i)


inline fun <T> first(items: List<T>, predicate: (T) -> Boolean): T {
for (item in items) {
if (predicate(item)) return item
}
throw Exception()
}

19 octombrie 2022

Kotlin - NULL handling - ziua 6

Java functional interfaces

Ex. Runnable, Callable 


variabila lambda este refolosita la al doilea apel;

variabila lambda nu mai poate fi refolosita la al doilea apel din cauza lui count;


Constructor SAM - pentru dezambiguizare (când compilatorul nu știe să transforme lambda în interfață funcțională)



Constrângeri de nulabilitate

Evitare NPE prin „cod defensiv” --> mult cod în plus

Kotlin:

- tipuri non-nullable

fun closeMeeting(m: Meeting): Boolean { // m: Meeting, deci nu poate fi null
return if (m.canClose()) m.close()
else false
}

fun main(args: Array<String>) {
closeMeeting(
null) // EROARE de COMPILARE
}


- tipuri nullable:  fun closeMeeting(m: Meeting?): Boolean

- safe calls: obj?.method()  === if (obj != null) obj.method()

- operatorul Elvis: newMeeting = m ?: Meeting()   === newMeeting = (m != null) ? m : new Meeting();

- safe cast:  val saveable = obj as? ISaveable    === saveable = obj instanceof ISaveable ? obj : null;

- not-null assertion:  m!!.close()  === assert (m != null) si arunca NPE daca s-a gasit null

- LET: cheama ce e in paranteze doar daca m != null

  m?.let { closeMeeting(m) }

- lateinit: Kotlin nu te lasă să declari o variabilă fără să fie inițializată. Soluții: inițializare cu o valoare default, cu null (și atunci devine nullable), sau cu lateinit (când știu că nu vreau să fie nullable).

  lateinit var address: Address // promisiune compilatorului că voi inițializa variabila


Interacțiune cu Java (adnotări)

public @Nullable String getTitle() {
  return meetingTitle;
}

public void setTitle(@NotNull String title) {
  this.meetingTitle = title;
}

// Kotlin
var title: String? = meeting.getTitle()


Platform type

Când nu există adnotări, compilatorul Kotlin știe că este doar un tip din Java, nu se știe dacă poate fi null sau nu, apare cu semnul exclamării, ex. String! = String sau String?
- dacă Kotlin implementează o interfață din Java unde există return type de tip platform, atunci return type al metodelor implementate poate fi atât nullable cât și non-nullable

15 octombrie 2022

Kotlin - Objects, High level functions & Filtre (ziua 5)

 object

- introduce un singleton (nu există constructor, instanțe)

- poate extinde un Comparator

- adnotare metodă din interiorul obiectului cu @JvmStatic pentru a putea fi chemată din Java

class Course(val id: Int, val title: String) {
}

object Courses {
var allCourses = arrayListOf<Course>()

init {
allCourses.add(Course(1, "Kotlin"))
allCourses.add(Course(2, "Maven"))
}
}

fun enroll(courseName: String){
val course = Courses.allCourses
.filter{it.title == courseName}
.firstOrNull()
}


Companion objects

- keyword: companion objects => Metodele din interiorul obiectului devin statice (factory methods)

open class Student : Person {
  // ....
  companion object : Internship<Student> {
    override fun applyToInternship(title: Student) {
TODO("Not yet implemented")
}

// adding static methods to the class
fun createUndergrad(name: String) = Undergrad(name)
fun createPostgrad(name: String) = Postgrad(name)
}
}

class Undergrad(name: String) : Student(name)

class Postgrad(name: String) : Student(name)

interface Internship<T> {
fun applyToInternship(title: T)
}


fun main(args: Array<String>) {
  Student.createPostgrad("Naim")
  Student.createUndergrad("Amir")
}


High level functions

program.fibonacci(8) { n -> println(n) }

program.fibonacci(8) { println(it) }

program.fibonacci(8, ::println)


Lambda

- pot schimba valori (in Java trebuie să fie final)

var total = 0

program.fibonacci(8) { it -> total += it }


with (student) {

  // asignari pe campurile obiectului student

  name = "Geo"

  city = "Bucharest"

}


student.apply {

  name = "Geo"

  city = "Bucharest"

}


Filter, map, predicate

val ints = listOf(1,2,3,4,5)
val smallInts = ints.filter { it < 4 }
for(i: Int in smallInts) println(i)

val sqInts = ints.map { it*it }
for(i: Int in sqInts) println(i)

val smallSqInts = ints.filter { it < 3 }.map { it*it }
for(i: Int in smallSqInts) println(i)

val largeInts = ints.all { it > 3 }
println(largeInts) // false: not all are grt than 3

val largeIntsAny = ints.any { it > 3 }
println(largeIntsAny) // true: there is one elem grt than 3

val grtThnThree = { v: Int -> v > 3 }
val largeCount = ints.count(grtThnThree)
println(largeCount) // 2

var found :Int? = ints.find(grtThnThree)
println(found) // 4 is the first elem found grt than 3

found = ints.find { it > 5 }
println(found) // null


Secvențe

- folosite atunci când listele create de filter/map ar fi imense

- folosesc evaluare leneșă

- se preferă secvențele în locul listelor

- în Java8, echivalentul este streams

Exemplu:

val titles = meetings.asSequence().filter { ... }.map { ... }

// for (i: String in titles) println(i)

Diferențe

- cu asSequence si fara println (comentat), nu se evalueaza deloc expresia (lazy)

- cu asSequence si println, ordinea este filtru + map + printare element din meetings, deoarece rezultatul este evaluat la cerere, cand este nevoie de el in println

- fara asSequence se evalueaza expresia indiferent daca rezultatul este sau nu folositor; ordinea este: toate filtrele, apoi toate maparile, apoi toate printarile

- cu asSequence operatiile pot fi mai eficiente, in special daca se cere doar primul rezultat (ca exemplu cu find = terminal operator)

06 octombrie 2022

KOTLIN - Clase (ziua 4)

 Interfețe

- public by default

- nu există implements / extends

interface Time {
fun setTime(hrs: Int, mins: Int = 0, secs: Int = 0)
fun setTime(time: String) = setTime(0) // default implementation
}

interface NoTime {
fun setTime(time: String) {}
}

class MyTime : Time, NoTime {
override fun setTime(hrs: Int, mins: Int, secs: Int) {}

override fun setTime(time: String) {
super<Time>.setTime(time)
super<NoTime>.setTime(time)

}
}


Clase

- public, final by default (și metodele sunt final by default)

- dacă vrei să nu fie final - se specifică open

In Java era o practică bună să adaugi final claselor care nu trebuiesc extinse

- suport pt abstract

- clase sigilate (sealed)

- internal: clase vizibile doar în modulul respectiv 

- protected, private; dar nu există package private

open abstract class Person () {
var firstName: String = ""
var lastName: String = ""

open fun getName(): String = "$firstName $lastName" // can be overriden

abstract fun getWork() // can be implemented

fun getVacations() {} // cannot be overriden
}

class Student : Person() {
override fun getName(): String{return ""}
override fun getWork() {
TODO("Not yet implemented")
}
}


Clase sigilate

- ierarhizare, asemănare cu enum

sealed class PersonEvent {
// nested subclasses
class Awake: PersonEvent()
class Asleep: PersonEvent()
class Eating(val food: String): PersonEvent()
}

fun handlePersonEvent(event: PersonEvent) =
when(event) {
is PersonEvent.Awake -> println("Awake")
is PersonEvent.Asleep -> println("Asleep")
is PersonEvent.Eating -> println("Eating ${event.food}")
}


Constructori

open class Person (_fname: String, _lname: String) {
var firstName: String = ""
var lastName: String = ""

init {
this.firstName = _fname
this.lastName = _lname
}

constructor(name: String) : this(name, "")
}


class Student : Person {
var age: Int;
init {
age = 0;
}

constructor(name: String) : super(name)

constructor(first: String, last: String) : super(first, last)

constructor(first: String, last: String, age: Int) : super(first, last) {
this.age = age;
}
}


Data classes

- furnizează metodele toString, equals, hashCode + metoda copy pentru clonare

- sunt clase imutabile

- introdusă prin keywork data class

fun main(args: Array<String>) {
var st1 = Steward(1, "Lina")
var st2 = Steward(1, "Lina")
var st3 = st2.copy(name = "Roberta")
// toate câmpurile la fel mai puțin name

println("Equal? ".plus(st1 == st2)) // true numai dacă există keyword data peste Steward
println(st3) // apelează toString, rezultat citibil față de un Steward@5e2de80c, dacă nu era data
}

data class Steward(val id: Int, val name: String)