스위프트 기초 시리즈
- Swift 기초 (1): 상수, 변수, 배열, 사전
- Swift 기초 (2): if 문, for ~ in 문, while 문, switch 문
- Swift 기초 (3): 함수 (function)
- Swift 기초 (4): 클래스, 옵셔널과 nil
- Swift 기초 (5): Enum (열거형; Enumeration)
- Swift 기초 (6): 프로토콜 (Protocol)
- Swift 기초 (7): 에러 처리 (Error Handling)
- Swift 기초 (8): 제네릭 타입 (Generic Type)
- Swift(스위프트): 클로저 (Closure) 1
클래스
선언
class Shape {
var numberOfSides = 0
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
인스턴스 생성
new
키워드를 입력하지 않습니다.
var shape = Shape() // new 키워드가 필요없음
shape.numberOfSides = 7 // 클래스 변수에 직접 접근 가능
var shapeDesc = shape.simpleDescription()
print(shapeDesc)
A shape with 7 sides.
초기화자 (Initializer)
초기화자는 다른 객체지향 언어의 생성자(Constructor
)와 비슷한 개념입니다.
class NamedShape {
var numberOfSides: Int = 0
var name: String
init(name:String) {
self.name = name
}
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
ar namedShape = NamedShape(name: "11각형")
namedShape.numberOfSides = 11
print(namedShape.simpleDescription())
A shape with 11 sides.
상속
상속의 특징은 다음과 같습니다.
class: 내클래스이름: 부모클래스이름 { ..... }
의 형태로 작성한다.- 부모클래스 키워드는
super
를 사용한다. - 오버라이딩시에는
override
키워드를 반드시 기입해야 한다.
class Square: NamedShape {
var sideLength: Double
// 상속받은 클래스는 상속한 클래스를 따라 초기화자가 반드시 있어야 함
init(sideLength: Double, name: String){
self.sideLength = sideLength // self 키워드 (나 자신) -> Square
super.init(name: name) // super 키워드 (부모 클래스) -> NamedShape
numberOfSides = 4
}
// 정사각형의 넓이 = 한 변의 길이의 제곱
func area() -> Double {
return sideLength * sideLength
}
// 오버라이딩 시에 override 키워드 반드시 필요
override func simpleDescription() -> String {
return "A square with sides of length \(sideLength)."
}
}
let test = Square(sideLength: 5, name: "test square")
print(test.area())
print(test.simpleDescription())
25.0
A square with sides of length 5.0.
퀴즈 1. NamedShape
클래스의 또 다른 하위 클래스인 Circle
을 작성하시오. 이 클래스는 이니셜라이저를 통해 radius
와 name
을 인자로 받는다. Circle 클래스 안에 area
, simpleDescription
함수를 구현하시오.
class Circle: NamedShape {
var radius: Double
init(radius: Double, name: String){
self.radius = radius
super.init(name: name)
}
func area() -> Double {
return pow(radius, 2) * Double.pi
}
override func simpleDescription() -> String {
return "A circle with area \(area())."
}
}
let test2 = Circle(radius: 10, name: "test circle")
print(test2.area())
print(test2.simpleDescription())
314.1592653589793
A circle with area 314.1592653589793.
프로퍼티 – getter/setter
getter/setter
를 비롯한 프로퍼티의 설정은 변수 선언 시 변수 이름 옆에 괄호 {}
로 묶은 다음 그 안에서 작성합니다. get
, set
키워드를 사용합니다. 또한 특이점으로 setter를 통해 들어오는 값은 newValue
라는 예약된 이름의 변수를 통해 다루게 됩니다.
아래 예제는 정삼각형 클래스입니다.
class EquilateralTriangle: NamedShape{
var sideLength: Double = 0.0
init(sideLength: Double, name: String){
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 3
}
// getter/setter
// newValue: setter에서 사용하는 예약된 키워드
var perimeter: Double { // perimeter: 둘레
get {
return 3.0 * sideLength
}
set {
sideLength = newValue / 3.0
}
}
override func simpleDescription() -> String {
return "An equilateral triagle with sides of length \(sideLength)."
}
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
// getter 사용
print(triangle.perimeter)
// setter 사용
triangle.perimeter = 9.9
print(triangle.sideLength)
9.3
3.3000000000000003
프로퍼티 – willSet/didSet
willSet
과 didSet
은 프로퍼티의 변경 후(willset
), 또는 변경 직전(didSet
)에 실행되는 setter입니다. 공통적으로 변경되는 값을 감지하는 기능이 있으며 두 기능의 차이는 실행 시점만 차이가 있습니다. 또한 초기화시에는 실행되지 않고, 초기화 이후에 값을 변경할 때에만 실행된다는 특징이 있습니다.
class TriangleAndSquare{
var triangle: EquilateralTriangle{
willSet{
square.sideLength = newValue.sideLength
print("triangle이 willSet되었습니다.")
}
}
var square: Square{
willSet{
triangle.sideLength = newValue.sideLength
print("square가 willSet되었습니다.")
}
}
init(size: Double, name: String){
square = Square(sideLength: size, name: name)
triangle = EquilateralTriangle(sideLength: size, name: name)
}
}
초기화시에는 willSet
이 동작하지 않습니다.
var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
print(triangleAndSquare.square.sideLength)
print(triangleAndSquare.triangle.sideLength)
10.0
10.0
초기화 이후 square
를 변경시에는 willSet
이 동작합니다.
triangleAndSquare.square = Square(sideLength: 50, name: "a larger square")
print(triangleAndSquare.triangle.sideLength)
square가 willSet되었습니다.
50.0
클래스 예제: 카운터
class Counter {
var count: Int = 0
func incrementBy(_ amount: Int, numberofTimes times: Int) {
count += amount * times
}
func outCount() -> Int {
return count
}
}
var counter = Counter()
counter.incrementBy(2, numberofTimes: 4)
print(counter.outCount())
8
옵셔널(optional)과 nil
변수의 타입 뒤에 물음표를 쓰면 이 변수는 옵셔널 값이라는 것을 나타냅니다. 옵셔널 변수란 nil
을 가질 수 있으면 옵셔널 변수, 가질 수 없다면 비 옵셔널 변수(non-optional) 입니다. 스위프트의 변수는 기본적으로 non-optional입니다.
그렇다면 nil
은 무엇일까요? nil
이란 변수에 어떤 값도 들어있지 않은 상태로 비슷한 것으로 null
이 있습니다.
옵셔널 변수를 선언하면 기본적으로 안에는 nil
상태입니다.
var optionalString: String?
print(optionalString == nil)
true
옵셔널 변수에 값을 넣으면 nil
상태가 아닙니다.
optionalString = "Hell"
print(optionalString == nil)
false
옵셔널 값은 if
문으로 다룰 수 있습니다. 이것을 언래핑(unwrapping
)이라 합니다. 옵셔널 값은 nil
의 가능성 때문에 논옵셔널 값과 같이 다뤄질 수 없으며, 언래핑을 통해 옵셔널 값을 언옵셔널로 바꾸는 과정을 거칩니다.
var optionalName: String? = "John Appleseed"
var greeting = "Hell!"
// optionalName에 값이 있다면 name 상수에 집어넣고
// "Hell, \(name)"을 greeting 에 할당하라.
if let name = optionalName {
greeting = "Hell, \(name)"
}
print (greeting)
Hell, John Appleseed
옵셔널 참고: http://monibu1548.github.io/2018/05/12/swift-optional/
퀴즈 1. optionalName에 nil을 할당하고, 할당된 값이 nil일 때 “Hell, Anonymous”을 greeting에 할당하도록 else 절을 추가하시오.
optionalName = nil
if let name = optionalName {
greeting = "Hell, \(name)"
} else {
greeting = "Hell, Anonymous"
}
print(greeting)
클래스에서 옵셔널 값 사용
let optionalSquare: Square? = Square(sideLength: 2.5, name: "Optional square")
let sideLength = optionalSquare?.sideLength
print(sideLength ?? "nil")
2.5
let optionalSquare2: Square? = nil
let sideLength2 = optionalSquare2?.sideLength
print(sideLength2 ?? "nil")
nil
??
연산자는 삼항 연산자가 더욱 간략화된 형태로. sideLength
가 nil
이 아니면 ??
앞에 있는 변수를 그대로 쓰고, 만약 nil
이라면 ??
뒤에 있는 변수를 사용하라는 의미입니다.
as – 형 변환 (Type Casting)
as?
: 형 변환이 될 것이 불확실할 때as!
: 형 변환이 될 것이 확실할 때, 주로 다운캐스팅에 사용
class Animal {
let name: String?
init(name: String) {
self.name = name
}
func move() -> (){
print("오른쪽으로 이동")
}
}
class Dog: Animal {
// Dog 전용 함수
func bark() -> () {
print ("멍멍")
}
}
class Frog: Animal {
// Frog 용으로 오버라이딩
override func move() -> (){
print("오른쪽으로 점프")
}
}
let someDogAsAnimal: Animal = Dog(name: "Dog Bird") // Dog
someDogAsAnimal.name ?? "nil" // Dog Bird
(someDogAsAnimal as! Dog).bark() // 멍멍
(someDogAsAnimal as? Dog) // Dog
let someFrogAsAnimal: Animal = Frog(name: "ggr")
someFrogAsAnimal.move() // 오른쪽으로 점프
스위프트 기초 시리즈
- Swift 기초 (1): 상수, 변수, 배열, 사전
- Swift 기초 (2): if 문, for ~ in 문, while 문, switch 문
- Swift 기초 (3): 함수 (function)
- Swift 기초 (4): 클래스, 옵셔널과 nil
- Swift 기초 (5): Enum (열거형; Enumeration)
- Swift 기초 (6): 프로토콜 (Protocol)
- Swift 기초 (7): 에러 처리 (Error Handling)
- Swift 기초 (8): 제네릭 타입 (Generic Type)
- Swift(스위프트): 클로저 (Closure) 1
0개의 댓글