페이지

2017년 2월 18일 토요일

Swift Inheritance, override, final

//Inheritance, override, final 


//Inheritance, override, final 

class Vehicle{
    var totalVehicles : Int = 0
    var desc:String {
        return "totalVehicles : \(totalVehicles)."
    }
}

class Bycle: Vehicle {
    override init(){
        super.init()
        self.totalVehicles = 2
    }
    override var desc : String {
        return super.desc + ", in bycle"
    }
    final func noOverrideMethod(){
        print("final keyword mean this cannot be allowed to override any more")
    }
}
class Bycle4Wheels : Bycle {
    override init(){
        super.init()
        self.totalVehicles = 4
    }

    override var desc : String {
        return super.desc + " with 4 wheels "
    }
}
var b = Bycle()
print( b.desc)
b.noOverrideMethod()
var f = Bycle4Wheels()
print( f.desc)

Swift Instance Method, Type Method,subscript

struct StructSample{
    static func typeMethod(){
        print("i am type method")
    }
    func instanceMethod(){
        print("i am instance method")
    }
}

var s = StructSample()
s.instanceMethod()
StructSample.typeMethod()

class ClassSample{
    //class keyword allow subclasses to override superclass implements
    class func typeMethod(){
        print("i am type method")
    }

    //static keyword not allow subclasses to override superclass implements 
    static func staticTypeMethod(){
        print(" static method from statcTypeMechod")
    }

    func instanceMethod(){
        print("i am instance method")
    }
}
var c = ClassSample()
c.instanceMethod()
ClassSample.typeMethod()


//static, class modifiers ?
class SomeClass {
    class var overrideType: Int {
        get {
            return 107
        }
    }
    static var type2 : Int  {
        get {
            return 1
        }
    }
}

print(SomeClass.overrideType)
print(SomeClass.type2)

//subscript
struct SubscriptSample{
    var weight : Int
    subscript(index:Int) -> Int {
        return index * weight
    }
}

var s = SubscriptSample(weight:3)
print( s[2],s[3])

2017년 2월 17일 금요일

Swift mutating

Modifying Value Types from Within Instance Methods Structures and enumerations are value types. By default, they cannot be modified from within its instance Methods However, if you want, you can opt in to "mutating" keyword. mutating The mutating keyword is added to its definition to enable it to modify its properties.


struct RectST {
    var x : Double = 0
    func minus(x dx:Int ){
       x -= dx     error: Left side of mutating operator isn't mutable: 'self' is immutable
    }
    mutating func move (x dx:Double){
        x += dx
    }
    mutating func moveSelf(x dx:Double){
        self = RectST(x:dx)
    }
}

class Rect {
    var x : Double = 0
    func move (x dx:Double){
        x += dx
    }
}

var c01 = RectST()
c01.minus(x:3)
c01.move(x:222) 

enum TriStateSwitch {
    case off,low,high
    mutating func next(){
        switch self {
            case .off:
                self = .low
            case .low:
                self = .high
            case .high:
                self = .off
                
        }
    }

}

Swift Lazy, Computed, Observers Properties

//1. Lazy Stored Properties

class DataImporter {
    var fileName = "data.txt"
}

class DataManager {
    lazy var importer = DataImporter()
    var data = [String]()
}



var m = DataManager()
m.data.append("data 1 ")
m.data.append("data 2 ")
//m.importer has not yet been created.
print( m.importer.fileName )
//m.importer has been created now.









//2. Computed Properties

struct Point {
    var x = 0.0, y = 0.0
}

struct Size {
    var width = 0.0, height = 0.0
}



struct Rect {
    var origin = Point()
    var size = Size()
    var center : Point {

        get {
            let tmpx = origin.x + size.width/2
            let tmpy = origin.y + size.height/2
            return Point(x:tmpx,y:tmpy)

        }

        // set {
        //     origin.x = newValue.x - size.width/2
        //     origin.y = newValue.y - size.height/2
        // }

     

        // renaming newCenter as newValue
        set ( newCenter ){
            origin.x = newCenter.x - size.width/2
            origin.y = newCenter.y - size.height/2
        }
    }
}



var r = Rect(origin:Point(x:10,y:10), size:Size(width:20,height:20))
print( r.center)



// 3. setter, getter

class Test {
   var _power : Double = 0.0
   var power : Double {
        get {
            return _power
        }

        set (newValue){
            _power = newValue
        }
    }
}







/* 4.Property Objservers


willSet is called just before the value is stored.
didSet is called immediately after the new value is stored.”

*/



class Sample {
    var force : Int = 0 {
        willSet(newV){
            print("\(force) -> \(newV)")
        }

        didSet {
            print("\(oldValue) -> \(force)")
        }
    }
}


var s = Sample()
print(s.force)
s.force = 12
print(s.force)

swift class and struct

Class have additional capablities that sturctures do not
 - Inheritance enables one class to inherit the characteristics of another. 
- Type casting enables you to check and interpret the type of a class instance at runtime. 
- Deinitializers enable an instance of a class to free up any resources it has assigned. 
- Reference counting allows more than one reference to a class instance. 

 Structures are always copied when they are passed around in your code, and do not use reference counting.

struct Resolution {
    var width = 0
    var height = 0
}

class VideoMode {
    var resolution = Resolution()
    var interlaced = false
    var framerate = 0.0
    var name: String?
}


var hd = Resolution(width:30,height:100)
var tmpHd = hd
tmpHd.width = 120


//sturct and enumeration are value types
print("sturct  \(hd.width) != \(tmpHd.width). copied")
var c = VideoMode()
c.resolution.width = 200
c.resolution.height = 300

var tmpC = c
tmpC.resolution.width = 120



/*
class is reference type
 identical operator : === , !==
*/

print("class \(c.resolution.width) == \(tmpC.resolution.width). reference")

if c === tmpC { 
    print ("class identical operator. equal")
}
// else if c !== tmpC






As a general guideline, consider creating a structure when one or more of these conditions apply:
- The structure’s primary purpose is to encapsulate a few relatively simple data values.
- It is reasonable to expect that the encapsulated values will be copied rather than referenced when you assign or pass around an instance of that structure.
- Any properties stored by the structure are themselves value types, which would also be expected to be copied rather than referenced.
- The structure does not need to inherit properties or behavior from another existing type. Examples of good candidates for structures include:
- The size of a geometric shape, perhaps encapsulating a width property and a height property, both of type Double.
- A way to refer to ranges within a series, perhaps encapsulating a start property and a length property, both of type Int. - A point in a 3D coordinate system, perhaps encapsulating x, y and z properties, each of type Double.”

Swift Enumerations : Raw value, Initializing, indirect


// Enumerations : Raw value

enum ASCIICharacterControl: Character {
    case tab = "\t"
    case lineFeed = "\n"
    case carriageReturn = "\r"
}

print("test\(ASCIICharacterControl.tab.rawValue)tabtab\(ASCIICharacterControl.lineFeed.rawValue)...")

enum Planet:Int {
    case sun=1,mercury,earth,mars,neptune,jupiter
}

print("\(Planet.sun),\(Planet.earth.rawValue)..")

enum CompassPoint: String {
    case east,west,south,north
}

print("\(CompassPoint.east)..\(CompassPoint.west.rawValue)")

// Enumerations : Initializing

var position = 3
if let planetTmp = Planet(rawValue: position) {
    switch planetTmp {
        case .earth:
            print("you choose \(planetTmp)")
        default:
            print("you choose other except earth:\(planetTmp)")
    }
} else {
    print("there is no planet with rawValue:\(position)")
}



//Recursive Enumerations : indirect

indirect enum ArithmethicExpression {
    case number(Int)
    case addition( ArithmethicExpression, ArithmethicExpression )
    case multiply( ArithmethicExpression, ArithmethicExpression )
}

let one = ArithmethicExpression.number(1)
let three = ArithmethicExpression.number(3)
let sum = ArithmethicExpression.addition(one,three)
let multi = ArithmethicExpression.multiply(sum,three)

func calculate(_ val: ArithmethicExpression ) -> Int {
    var ret : Int = 0
    switch val {
        case .number( let n ):
            ret = n
        case let .addition( a, b ):
            ret = calculate(a) + calculate(b)
        case let .multiply ( a, b ):
            ret = calculate(a) * calculate(b)
        default:
            print("nothing \(val)")
    }
    return ret
}
print( calculate(sum))
print( calculate(multi))

Swift Enumeration,Associated values

//1. Enumerations



enum SomeEnumeration {

}

enum CompassPoint {
    case north
    case south
    case east
    case west
}

enum Planet {
    case Sun,Mercury,Earth,Mars,Jupiter,Neptune
}

var directionToHead = CompassPoint.north
print(directionToHead)
directionToHead = .west
print(directionToHead)

switch directionToHead {
    case .north:
        print("switch: \(directionToHead)")
    case .south:
        print("switch: \(directionToHead)")
    case .east:
        print("switch: \(directionToHead)")
    case .west:
        print("switch: \(directionToHead)")
}


//2. Associated Values

enum BarCode {
    case upc(Int,Int,Int,Int)
    case qrCode(String)
}

var bCode = BarCode.upc(1,3,4,66)
print(bCode)
bCode = .qrCode("hi hello")
print(bCode)

switch bCode {
    case .upc(let leftPos,let topPos,let rightPos,let bottomPos):
        print ("upc \(leftPos), \(topPos), \(rightPos), \(bottomPos)")
    case let .qrCode(name):
        print ("hey \(name)")
}

Swift autoclosure

// 1. Closure - Autoclosure
“An autoclosure is a closure that is automatically created to wrap an expression that’s being passed as an argument to a function. It doesn’t take any arguments, and when it’s called, it returns the value of the expression that’s wrapped inside of it. This syntactic convenience lets you omit braces around a function’s parameter by writing a normal expression instead of an explicit closure.”





var customersInLine = ["james","kim","lee","richard","micheal","blondes","linda"]
let customerProvider = { customersInLine.remove(at:0) } // autoclosure : ()->String
print( customersInLine.count )
print( customerProvider() )
print( customersInLine.count )



//not autoclosure

func serve(customer: ()->String){
    print("serve:\(customer())")
}

serve(customer: { customersInLine.remove(at:0) } )
print (customersInLine.count)


//autoclosure
func serveAutoclosure(customer: @autoclosure ()->String ){
    print("serve by Autoclosure:\(customer())")
}
serveAutoclosure(customer: customersInLine.remove(at:0))
print (customersInLine.count)



// + escaping
var tempClosures : [()->String] = []
func collectClosures(itemClosure: @autoclosure @escaping ()->String){
    tempClosures.append(itemClosure)
}
collectClosures(itemClosure: customersInLine.remove(at:0))
collectClosures(itemClosure: customersInLine.remove(at:0))
for i in tempClosures {
    print("customer:\(i()), count:\(customersInLine.count)")
}


Swift closure : Capturing value, Escaping Closures

//1. Closure : Capturing value


func makeIncrement( forIncrement amount: Int) -> ()->Int {
    var sum = 0 // this is captured value
    func add () -> Int {
        sum += amount
        return sum
    }
    return add
}

let incrementBy5 = makeIncrement(forIncrement:5)
print(incrementBy5())
print(incrementBy5())
let incrementBy3 = makeIncrement(forIncrement:3)
print(incrementBy3())
print(incrementBy3())


//Closures are Reference Type
let incrementTemp = incrementBy3
print(incrementTemp())


//2. Closure : Escaping Closures
/*
A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns.
*/

var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping  () -> Void) {
    completionHandlers.append(completionHandler)    
    // closure is not called in this scope. @escaping required
    // completionHandler() // closure is called in this scope. @escaping not required
}

func someFunctionWithNonescapingClosure(closure: () -> Void) {
    closure()
}

class SomeClass {
    var x = 10
    func doSomething() {
        someFunctionWithEscapingClosure { self.x = 100 }
        someFunctionWithNonescapingClosure { x = 200 }
    }
}

let instance = SomeClass()
instance.doSomething()
print(instance.x)
// Prints "200"
completionHandlers.first?()
print(instance.x)
// Prints "100”


Swift nested function, closure

// 1. nested function return type

func sumOrSub(enable:Bool) -> (Int,Int)->Int {
    func add(_ a: Int, _ b:Int )->Int {
        return a+b
    }

    func sub(_ a:Int , _ b:Int)->Int {
        return a - b
    }

    if(enable){
        return add
    }
    else {
        return sub
    }

}

print( sumOrSub(enable:true)(1,2))





// 2. closure

let names = ["james","charile","richard","hong","kim","lee"]
func backward(_ a:String, _ b:String)->Bool {
    return (a > b )
}
var reversed = names.sorted(by:backward)
print (reversed)

reversed = names.sorted(by: { (a:String, b:String)->Bool in return a>b })
print (reversed)

reversed = names.sorted(by: { s1,s2 in return s1>s2 })
print( reversed) 

reversed = names.sorted(by: { s1,s2 in s1>s2 })
print( reversed) 


reversed = names.sorted(by: { return $0>$1})
print( reversed)


reversed = names.sorted(by: { $0>$1})
print( reversed)

reversed = names.sorted(by: > )
print( reversed)


//trailing closure

reversed = names.sorted(){ $0>$1}
print( reversed)
reversed = names.sorted{ $0>$1}
print( reversed)
reversed = names.sorted{ ( a, b) -> Bool in return a > b }
print( reversed)

Swift multiples return, variadic parameters, in-out parameters

// 1. multiples return values

func limitArray(array: [Int])->(min:Int, max:Int){
    var tmpMin = 0,tmpMax = 0
    for t in array {
        if tmpMax < t {
            tmpMax = t
        }
        if tmpMin > t {
            tmpMin = t
        }
    }
    return (tmpMin, tmpMax)

}

let limit = limitArray( array: [2,5,1,6,7,8,11])
print( limit.min, limit.max)


// 2. Variadic parameters
func average(_ vals: Int...)->Double {
    var sum  = 0
    for val in vals {
        sum += val
    }
    return Double(sum) / Double(vals.count )
}

print( average(1,2,3,4,5) )


// 3. In-Out parameters

func swapInt(_  a: inout Int, _ b: inout Int ){
    let tmp = a
    a = b
    b = tmp
}
var a2 = 11
var b2 = 2
swapInt(&a2, &b2)
print(a2,b2)


Swift loop, guard

//2. label loop

let finalSquare = 25
var board = [Int](repeating: 0, count: finalSquare + 1)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
var square = 0
var diceRoll = 0

gameLoop: while square != finalSquare {
    diceRoll += 1
    if diceRoll == 7 { diceRoll = 1 }
    switch square + diceRoll {
    case finalSquare:
        // diceRoll will move us to the final square, so the game is over
        break gameLoop
    case let newSquare where newSquare > finalSquare:
        // diceRoll will move us beyond the final square, so roll again
        continue gameLoop
    default:
        // this is a valid move, so find out its effect
        square += diceRoll
        square += board[square]
    }
}
print("Game over!")


//3. guard

func greet(person: [String: String]) {
    guard let name = person["name"] else {
        return
    }
    print("Hello \(name)!")

}
greet(person: ["addr": "south korea, seoul"])
greet(person: ["name": "hjkim"])


// 4. checking API availability

if #available(iOS 10, macOS 10.12, *) {
    // Use iOS 10 APIs on iOS, and use macOS 10.12 APIs on macOS
} else {
    // Fall back to earlier iOS and macOS APIs
}