/*Ex 1*/
class SomeType {
}
// extension 키워드 붙여서 확장
extension SomeType {
// 새로운 기능(메서드) 추가
func doSomething() {
print("hi")
}
}
/*Ex 2*/
class Person {
var id = 0
var name = "이름"
var email = "1234@gmail.com"
func walk() {
print("사람이 걷는다")
}
}
class Student: Person {
var studentId = 1
override func walk() {
print("학생이 걷는다")
}
func study() {
print("학생이 공부한다")
}
}
// Student 확장
extension Student {
func play() {
print("학생이 논다")
}
}
class Undergraduate: Student {
var major = "전공"
override func walk() {
print("대학생이 걷는다.")
}
override func study() {
print("대학생이 공부한다.")
}
func party() {
print("대학생이 파티한다.")
}
/* swift에서는 상위 클래스의 확장에서 정의한 메서드는 재정의가 불가능하다!! (@objc 붙이면 가능)
override func play() { // 에러
print("대학생이 논다")
}*/
}
var a = Undergraduate()
a.play() // 학생이 논다. -> 확장한 것도 자동으로 상속
/*확장의 장점 - 소급 모델링 (retroactive modeling)*/
Int -> 하나의 struct
-> 확장해서 새로운 메서드를 추가할 수 있다!!
extension Int {
var squared: Int {
return self * self
}
}
5.squared // 25
재정의는 상속에서!! 확장에서는 새로운 기능을 추가할 뿐
확장 가능한 멤버 종류
타입 계산 속성
extension Double {
static var zero: Double { return 0.0 }
}
Double.zero // 0.0
인스턴스 계산 속성
extension Double {
var km: Double { return self * 1_000.0 }
var m: Double { return self }
var cm: Double { return self / 100.0 }
var mm: Double { return self / 1_000.0 }
var ft: Double { return self / 3.28084 }
}
let oneInch = 25.4.mm
print("1인치는 \(oneInch) 미터") // "1인치는 0.0254 미터"
let threeFeet = 3.ft
print("3피트는 \(threeFeet) 미터") // "3피트는 0.914399970739201 미터"
let aMarathon = 42.km + 195.m
print("마라톤은 \(aMarathon) 미터의 길이임")
타입 메서드
Int.random(in: 1...100)
extension Int {
static func printNumbersFrom1to5() {
for i in 1...5 {
print(i)
}
}
}
Int.printNumbersFrom1to5()
인스턴스 메서드
extension String {
func printHelloRepetitions(of times : Int) {
for _ in 0..<times {
print("Hello \(self)!")
}
}
}
"Steve".printHelloRepetitions(of: 4) // Hello Steve! x4
구조체, 열거형에서, 자신의 속성을 변경하는 메서드는 mutating 키워드
extension Int {
mutating func square() {
self = self * self // 값을 직접적으로 변경
}
}
var someInt = 3
someInt.square() // 9
// 기존 생성자
var color = UIColor(red: 0.3, green: 0.5, blue: 0.4, alpha: 1)
// 편의 생성자 추가
extension UIColor {
convenience init(color: CGFloat) {
self.init(red: color/255, green: color/255, blue: color/255, alpha: 1) // original의 지정 생성자를 호출해야 한다
}
}
UIColor(color: 1)
애초에 편의 생성자가 존재하지 않음
비슷하게 original의 지정생성자 호출하는 방식은 존재
struct Point {
var x = 0.0, y = 0.0
init() {
self.init(x: 0.0, y: 0.0)
}
init(x: Double, y: Double) {
self.x = x
self.y = y
}
}
(편의 생성자와 비슷하게) 생성자를 추가하여 original의 지정 생성자 호출하는 방식으로도 구현 가능하고
새롭게 지정생성자 형태로 구현하는 것도 가능하다
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()
}
let defaultRect = Rect()
let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0),
size: Size(width: 5.0, height: 5.0))
extension Rect {
// center값으로 직사각형을 만드는 생성자
init(center: Point, size: Size) {
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
self.init(origin: Point(x: originX, y: originY), size: size)
// 예외 케이스
// self.origin = Point(x: originX, y: originY)
// self.size = size
}
}
let centerRect = Rect(center: Point(x: 4.0, y:4.0),
size: Size(width: 3.0, height: 3.0))
extension Int {
subscript(num: Int) -> Int {
var decimalBase = 1
for _ in 0..<num {
decimalBase *= 10
}
return (self / decimalBase) % 10
}
}
123456789[0] // (123456789 / 1) ==> 123456789 % 10 ==> 나머지 9
123456789[1] // (123456789 / 10) ==> 12345678 % 10 ==> 나머지 8
123456789[2] // (123456789 / 100) ==> 1234567 % 10 ==> 나머지 7
123456789[3] // (123456789 / 1000) ==> 123456 % 10 ==> 나머지 6
extension Int {
enum Kind { // 음수인지, 0인지, 양수인지
case negative, zero, positive
}
var kind: Kind { // 계산 속성으로 구현
switch self {
case 0: // 0인 경우
return Kind.zero
case let x where x > 0: // 0보다 큰경우
return Kind.positive
default: // 나머지 (0보다 작은 경우)
return Kind.negative
}
}
}
func printIntegerKinds(_ numbers: [Int]) {
for number in numbers {
switch number.kind {
case .negative:
print("- ", terminator: "")
case .zero:
print("0 ", terminator: "")
case .positive:
print("+ ", terminator: "")
}
}
print("")
}