iOS Development/Swift
[Swift] #6 - Class
se0m
2021. 9. 3. 12:34
** 객체지향 프로그래밍
- 객체로 프로그램을 구성
- 객체: 정보(변수) + 동작(함수)
- 객체를 만들 때는 클래스라는 설계도를 이용해서 만듬
** 객체지향의 용어
- 객체: 데이터, 행위, 아이덴티티를 가지고 있는 것
- 클래스: 객체를 생성하는 틀
- 캡슐화: 행위와 상태를 포장하고 외부에 노출할 것과 감출 것을 결정하는 것
- 상속: 코드의 재사용성과 계층구조의 표현
- 다형성: 캡슐화, 상속과 함께 동작함으로써 객체-지향 프로그램의 흐름 제어를 단순화하는 것
** 클래스 정의
- 프로퍼티 = 멤버 변수 = 속성
// Class
// '사용자 정의 타입'
// 클래스 정의
class SimpleClass {
var name = "SimpleClass"
var count = 0
}
// 객체 생성
var simpleClass = SimpleClass()
var simpleClass1 = SimpleClass()
// 객체 내부 접근
simpleClass.count = 1
simpleClass1.count = 2
var count = simpleClass.count
print(simpleClass.count)
print(simpleClass1.count)
** 클래스 정의 - 메소드
// 클래스 정의 - 메소드
class Vehicle {
var speed = 0.0
var mile:Double {
// return Double(speed) * 0.6213
// 속성값을 읽을 때는 get이 동작
get {
return Double(speed) * 0.6213
}
// 속성값을 사용할 때는 set이 동작
set(newValue) {
if newValue > 0 { // 제한두기 가능
speed = newValue * 1.6
} else {
speed = 0
}
}
}
func speedUp() {
speed += 10
}
func speedDn() {
speed -= 10
}
func speed2Mile() -> Double {
return Double(speed) * 0.6213
}
}
var someVehicle = Vehicle()
someVehicle.speedUp()
print("changed speed = \(someVehicle.speed)")
print(someVehicle.speed2Mile())
print(someVehicle.mile)
someVehicle.mile = 94
print(someVehicle.speed)
** 연산 프로퍼티
- 메소드와 하는 일은 같지만, 데이터가 중심일 때 사용하고 메소드에 비해 액션이 많지 않음
- 연산 후 값을 저장하는 프로퍼티
** getter / setter
- read-only 인 경우, setter 생략 가능
- 올바른 값만 저장할 수 있도록 함 -> 캡슐화 (속성에 직접 접근 불가)
** 예제
// 클래스 정의 실습
// 정사각형 클래스
class Rectangle {
var width = 0.0; var height = 0.0 // 초기화하지 않으면 ERROR -> 선언만 하고 할당되지 않은 상태: nil(= null)
var area:Double {
get { width * height }
set(newVal) {
width = sqrt(newVal)
height = width
}
}
}
var rec = Rectangle() // 생성자가 정의되어 있지 않을 경우 자동으로 생성해줌
rec.width = 2
rec.height = 3
print("사이즈 변경 후 넓이: \(rec.area)")
rec.area = 100
print("넓이 변경 후 너비: \(rec.width)")
** 클래스 정의 - 생성자
- 생성자: 멤버 변수를 초기화하고 메모리 공간을 할당(인스턴스화)
- init이 하나도 없을 경우, 내부적으로 자동으로 생성하여 실행함
// 클래스 정의 - 생성자
class Square1 {
var width:Double; var height:Double // 생성자에서 초기화해주므로 값을 할당하지 않았어도 ERROR가 나지 않음
var area:Double {
get {
return width * height
}
set(newVal) { // area 값이 수정되면
width = sqrt(newVal) // width, height 값도 변경
height = width
}
}
func duplicate() -> (Double, Double) {
width *= 2
height *= 2
return (width, height)
}
// 생성자
init(w:Double, h:Double) {
width = w
height = h
}
}
var square1 = Square1(w:10, h:10)
print(square1.area)
square1.area = 25
print("width = \(square1.width) / height = \(square1.height)")
square1.duplicate()
print(square1.area)
** 클래스 정의 - self
- self: 클래스 변수
// 클래스 정의 - self
class Square2 {
var width:Double; var height:Double
var area:Double {
get { return width * height }
set(newVal) { width = sqrt(newVal); height = width }
}
func duplicate() -> (Double, Double) {
width *= 2
height *= 2
return (width, height)
}
init(width:Double, height:Double) {
self.width = width
self.height = height
self.duplicate()
}
}
** 클래스의 상속
- Super class: 부모 클래스 / 공통 기능 재사용 가능
- Sub class: 자식 클래스
** 상속의 구현
- 클래스 정의시 상속 받을 클래스를 명시함
- 해당 클래스에 메소드가 없을 경우, 부모 클래스에서 찾아 실행함
// 클래스 상속
class Car:Vehicle {
var wheelCount:Int; var seatCount:Int
func shiftGear() {
print("변속")
}
init(wheelCount:Int, seatCount:Int) {
self.wheelCount = wheelCount
self.seatCount = seatCount
}
}
var car = Car(wheelCount: 4, seatCount: 2)
car.speedUp() // 부모 클래스의 메소드 실행
print(car.speed) // 부모 클래스의 멤버 변수 접근
** 예제
- var truck = Truck(): ERROR
// 클래스 상속 실습
class Truck:Car {
var loadage:Int = 0
func load() {
print("load")
}
func unLoad() {
print("unLoad")
}
}
var truck = Truck(wheelCount: 6, seatCount: 2) // Truck에 생성자가 없지만 그 부모 클래스에 존재하므로
truck.load()
truck.unLoad()
** 메소드 재정의
- 오버라이딩: 부모 메소드 재정의
// 부모 메소드 재정의
class Truck1:Car {
var loadage:Int = 0
func load() {
print("load")
}
func unLoad() {
print("unLoad")
}
// 오버라이딩
override func speedUp() {
speed += 5
}
}
class SportsCar:Car {
override func speedUp() {
speed += 20
}
}
var testCar = Car(wheelCount: 4, seatCount: 4)
testCar.speedUp()
print(testCar.speed)
var testTruck = Truck1(wheelCount: 6, seatCount: 2)
testTruck.speedUp()
print(testTruck.speed)
var testSportsCar = SportsCar(wheelCount: 4, seatCount: 2)
testSportsCar.speedUp()
print(testSportsCar.speed)
** 생성자 재정의
// 생성자 재정의
class Truck2:Car {
var loadage:Int
func load() { print("load") }
func unLoad() { print("unLoad") }
init(loadage:Int, wheelCount:Int, seatCount:Int) {
self.loadage = loadage // 자신
super.init(wheelCount: wheelCount, seatCount: seatCount) // 부모의 생성자
}
override func speedUp() {
speed += 5
}
}
var truck2 = Truck2(loadage: 1000, wheelCount: 6, seatCount: 2)
print(truck2.loadage)
// 다형성: 같은 부모 다른 자식
class Sedan:Car {
func loadPassenger() {
print("Load Passanger")
}
override func shiftGear() {
print("자동 변속")
}
}
class Bus:Car {
func loadCargo() {
print("Load Cargo")
}
override func shiftGear() {
print("수동 변속")
}
}
var sedan = Sedan(wheelCount: 4, seatCount: 5)
sedan.shiftGear()
var bus = Bus(wheelCount: 4, seatCount: 50)
bus.shiftGear()