스위프트 문법 : Type Casting (as! as? as, is) and Any (영)

김영채 (Kevin)·2021년 1월 31일
0

iOS & Swift

목록 보기
61/107
post-thumbnail
let myDouble = 0.0
let myDoubleAsInt = Int(myDouble)
//myDoubleAsInt: Int

→ The above code is not really "Type casting". The type conversion that is happening above is achieved through " initialization "

Is

  • Checks if a certain object is of a specific data type
  • Used for type-checking

ex. "is" example

class Animal{
    var name: String
    
    init(n: String){
        name = n
    }
}

class Human: Animal{
    func code(){
        print("coding..")
    }
}

class Fish: Animal{
    func breatheUnderWater(){
        print("breathing..")
    }
}

let angela = Human(n: "Angela")
let jack = Human(n: "Jack")
let nemo = Fish(n: "Nemo")

let neighbours = [angela, jack, nemo]
//neighbours array is type of "Animal"

if neighbours[2] is Human{
    print("is human")
}
//false -> nemo is type of fish

func findNemo(from animals: [Animal]){
	for animal in animals{
		if animal is Fish{
			print(animal.name)
		}
	}
}

findNemo(from: neighbours) 
//Nemo

ex. another example

let cell = UITableViewCell()

if cell is UITableViewCell{
	print("it is!")
}

as!

  • Used for Type Casting as well
  • Forced Downcast
func findNemo(from animals: [Animal]){

	for animal in animals{

		if animal is Fish{
			print(animal.name)
		}
	}
}

→ In the for-loop, animal is the type of Animal, thus we cannot tap into the "breatheUnderWater( )" method right now.

→ But once we are totally sure that animal is of type Fish, we can downcast it and assign it to a different variable/constant.

func findNemo(from animals: [Animal]){

	for animal in animals{

		if animal is Fish{
			
			let fish = animal as! Fish
			fish.breatheUnderWater()
		}
	}
}

findNemo(from: neighbours) 
//breathing..

→ Force downcast : need to be very careful when using it.

ex.

let fish = neighbours[1] as! Fish
//run-time error

as?

  • To prevent run-time errors like the one above, we could use "as?"
  • It's a safer way to downcast
let fish = neightbours[1] as? Fish
//fish becomes type of Fish? (Optional)

fish?.breatheUnderWater()
//Optional chaining -> Checks if fish is not nil, and then performs method

//OR

if let fish = neightbours[1] as? Fish{
	fish.breatheUnderWater()
		//Optional binding -> no need for chaining 
}
else{
	print("casting failed")
}
//casting failed

as

  • Upcasting

  • Raise an object to its superclass type

  • No need to add ? or ! because it is always going to succeed in casting.

    → Because it's just raising it to its superclass. A subclass "always" has a superclass

func findNemo(from animals: [Animal]){

	for animal in animals{

		if animal is Fish{
			
			let fish = animal as! Fish
			fish.breatheUnderWater()
		
			let animalFish = fish as Animal
			//animalFish: Animal
		}
	}
}

Any, AnyObject, NSObject

  • It allows the code to accept any data type

let angela = Human(n: "Angela")
let jack = Human(n: "Jack")
let nemo = Fish(n: "Nemo")
let num = 12

let neighbours = [angela, jack, nemo, num]
//error

let neighbours: [Any] = [angela, jack, nemo, num]
// no error

→ Making an array with type Any allows it to accept any kind of data type

  • num is created from a "structure", while others are instances of a "class"

AnyObject

let neighbours: [AnyObject] = [angela, jack, nemo, num]
//error (num not allowed)
  • But if we make neighbours an array of AnyObject, we get an error.

Why?

A. AnyObject restricts the types to those that comes from classes. Structures are no longer allowed. Int, Double, String are all structures, so they are not allowed.

ex.

class Fish: Animal{
    func breatheUnderWater(){
        print("breathing..")
    }
}

struct Fish{
    func breatheUnderWater(){
        print("breathing..")
    }
}

let neighbours: [AnyObject] = [angela, jack, nemo]
//error
  • If we change the above class to a structure, we also get an error for neighbours array. Nemo instance is no longer a class instance, it's a structure.

NSObject

let neighbours: [NSObject] = [angela, jack, nemo]
//error

If we make the array as an NSObject type, we get an error. This is because angela, jack, nemo all do not fit to the NSObject.

→ We need to use a class from Foundation, which is made by Apple

let num: NSNumber = 12
let word: NSString = "ABC"

let neighbours: [NSObject] = [num,word]
// This is okay

→ So, depending on how strict your criteria is, you can go through these very broad types : Any, AnyObject, and NSObject. These allow you to create collections of items that are more broad than just writing like "let neightbours: [Animals]"

profile
맛있는 iOS 프로그래밍

0개의 댓글