воскресенье, 5 июля 2020 г.

Swift, Access Control

Online Swift Playground 

- private
- fileprivate
- internal (default)
- public
- open

//weapon.swift
public protocol Weapon {
    var ammo: Int {get}
}

//gun.swift
internal class Gun: Weapon {
    private(set) var ammo: Int
    fileprivate(set) var isEmpty: Bool

    init(ammo: Int = 3){
        self.ammo = ammo
        self.isEmpty = false
    }

    func fire() {
        guard self.ammo > 0 else {
            print("Out of ammo!")
            self.isEmpty = true
            return
        }
        self.ammo -= 1
        print("Fire!")
    }

    func reload(ammo: Int = 3){
        self.ammo = ammo
        print("Reloading!")
        self.isEmpty = false
    }
}

//main.swift
var g1 = Gun()
print("ammo: \(g1.ammo)")
while !g1.isEmpty {
    g1.fire()
}
//g1.ammo = 3 //error
g1.reload()
print("ammo: \(g1.ammo)")

четверг, 2 июля 2020 г.

Swift, Generics, Constraints

Online Swift Playground 

//Generics
func add<T: AdditiveArithmetic>(a: T, b: T) -> T {
    return a + b
}
let sum = add(a: 5, b: 5)
print("5 + 5 = \(sum)")

class Point<T>{
    var x:T
    var y:T

    init(x:T, y:T){
        self.x = x
        self.y = y
    }
}

let p1 = Point<Int>(x: 1, y: 2)
let p2: Point<Float> = Point(x: 1.0, y: 2.0)
let p3 = Point(x: 1.0, y: 2.0)
print(p3)

//Constraints
protocol Shape{
    func area() -> Double
}

class Rect: Shape{
    var w: Double
    var h: Double

    init(w:Double, h: Double){
        self.w = w
        self.h = h
    }

    func area() -> Double {
        w * h
    }
}

class Figures<T: Shape>{
    var figures: [T]

    init(figures: [T]){
        self.figures = figures
    }
}

extension Array where Element: Rect {
    func area(){
        forEach { print("area: \($0.area())")}
    }
}

let arr1 = [Rect(w:1, h:1), Rect(w:2, h:2)]
let fig1 = Figures(figures: arr1)
fig1.figures.area()

//associatedtype
protocol Drawable {
    associatedtype Sprite where Sprite: Rect
    func draw(sprite: Sprite)
}

//conditional
protocol Updatable{
    func update()
}

extension Int: Updatable{
    func update(){
        print("update")
    }
}

extension Array: Updatable where Element: Updatable {
    func update(){
        forEach { $0.update()}
    }
}

let arr2 = [1, 2, 3]
1.update()
arr2[0].update()
arr2.update() //x3

//Array
let arr0 = [1, 2, 3] //inference
let arr3: [Int] = [1, 2, 3] //sugar
let arr4 = [Int]() //sugar
let arr5: Array<Int> = [1, 2, 3] //generic
let arr6 = Array<Int>() //generic

//Dictionaries
let dic0 = [1 : "Mike", 2 : "Tom"] //inference
let dic1: [Int : String] = [1 : "Mike", 2 : "Tom"] //sugar
let dic2: [Int : String] = [ : ] //sugar
let dic3: Dictionary<Int, String> = [1 : "Mike", 2 : "Tom"] //generic

//Optionals
enum Optional<T> {
    case some(T)
    case none
}

var op1: Optional<Int> = Optional.some(5)
var op2 = Optional<Int>.some(5)
var op3 = Optional.some(5)
//if op3 == Optional<Int>.none{print("nil")}

var op4: Int? = 5
if op4 == nil {print("nil")}

Swift, Protocols, Standard Library

Online Swift Playground 

//Equatable
struct Point{
    var x: Int
    var y: Int
}

extension Point: Equatable {
    static func ==(lhs: Point, rhs: Point) -> Bool {
        lhs.x == rhs.x && lhs.y == rhs.y
    }
}

var p1 = Point(x:1, y:1)
var p2 = p1
print("p1 equal p2: \(p1 == p2)")

//Comparable
extension Point: Comparable {
    static func <(lhs: Point, rhs: Point) -> Bool {
        if lhs.x == rhs.x {
        return lhs.y < rhs.y
        }
        return lhs.x < rhs.x
    }
}

var p3 = Point(x:3, y:3)
print("max: \(p1 < p3 ? p3 : p1)")

var p4 = Point(x:4, y:4)
var p5 = Point(x:5, y:5)

var pArr = [p5, p2, p1, p4, p3]
print(pArr)
pArr.sort()
print(pArr)
print(pArr.max()!)
print(pArr.min()!)
print(pArr.contains(p1))
print(pArr.starts(with: [p1, p2]))
pArr.reverse()
print(pArr)

//Hashable
class Person: Hashable{
    let name: String

    init(name: String){
        self.name = name
    }

    static func ==(lhs: Person, rhs: Person) -> Bool {
        lhs.name == rhs.name
    }
  
    func hash(into hasher: inout Hasher) {
        hasher.combine(name)
    }
}

let person = Person(name: "Mike")
let dic1 = [person: "1973"]
print(dic1)

//CustomStringConvertible, CustomDebugStringConvertible
extension Person: CustomStringConvertible {
    var description: String {
        "\(name)"
    }
}
print(dic1)

extension Person: CustomDebugStringConvertible {
    var debugDescription: String {
        "Person: \(name)"
    }
}
debugPrint(dic1)

среда, 1 июля 2020 г.

Swift, Protocols (interfaces)

Online Swift Playground 

//Protocols - value types (structs and enums) OR reference types (classes)
protocol Drawable {
    var image: String {get set}
    init?(image: String)
    func draw()
}

protocol Transform {
    associatedtype PosType
    var position: PosType {get set}
}

protocol Movable: Transform {
    var speed: Double {get set}
    func move(speed: Double)
}

class Sprite: Drawable, Movable{
    //typealias PosType = (x: Double, y: Double)
    var position: (x: Double, y: Double)
    var image: String
    var speed: Double = 0

    required init?(image: String){
        guard image != "" else {
            return nil
        }
        self.image = image
        self.position = (x:0, y:0)
    }

    func draw() {
        print("sprite: \(image)")
    }

    func move(speed: Double){
        self.speed = speed
        self.position.x += speed
        self.position.y += speed
        print("speed: \(self.speed)")
    }
}

var s1 = Sprite(image: "image.png")!
s1.draw()
s1.move(speed: 2.4)
print("position: \(s1.position)")

var drawType: Drawable.Type = Sprite.self
print(drawType)
let d1 = drawType.init(image: "image1.png")
d1?.draw()

var s2 = Sprite(image: "image2.png")!
var s3 = Sprite(image: "image3.png")!

let sprites:[Drawable] = [s1, s2, s3]

for sprite in sprites{
    sprite.draw()
}

//extensions, composition
protocol Sizable{
    var size: Double{get}
}

extension Sprite: Sizable{
    var size: Double { 1.0 }
}

func render(sprite: Drawable & Sizable){
     sprite.draw()
     print("size: \(sprite.size)")
}
render(sprite: s1)

//value types
protocol Weightable{
    var weight: Int {get set}
}

struct Box: Weightable{
    var size: String = "big"
    var weight: Int = 1
}

var sp1: Weightable = Box()
print(sp1.weight)
print((sp1 as! Box).size)
var sp2 = sp1 //copy
sp2.weight = 2
print(sp1.weight)
print(sp2.weight)

//ref types - only for classes
protocol RefWeightable: class{
    var weight: Int {get set}
}

//...