// 기존 타입
class SomeType { }
// 확장
// 기존의 타입에 extension 이라는 키워드를 사용해서 확장
// 새로운 기능을 추가 가능(메서드 형태만 가능)⭐️
// 확장에서 구현한 메서드에 대한 재정의가 불가⭐️(@objc 붙이면 가능)
extension SomeType { }
[사람 → 학생(상속) → 대학생(상속) 구조의 클래스에서]
extension Int {
// 타입속성이므로 Int.ten으로 10을 사용할 수 있다
static let ten = 10
// 계산속성이므로 인스턴스에서 접근하면 된다
// 10.sqared로 100을 사용할 수 있다
var squared: Int {
return self * self
}
// 메서드이므로 인스턴스에서 접근하면 된다
// 10.double()로 100을 사용할 수 있다
func double() -> Int{
return self * self
}
}
extension Double {
static var zero: Double { return 0.0 }
}
Double.zero
extension Double {
// 인스턴스 자신에 1000 곱하기
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
// 1인치는 0.0254 미터"
print("1인치는 \(oneInch) 미터")
let threeFeet = 3.ft
// 3피트는 0.914399970739201 미터"
print("3피트는 \(threeFeet) 미터")
extension Int {
//구조체의 타입 메서드
static func printNumbersFrom1to5() {
for i in 1...5 {
print(i)
}
}
}
Int.printNumbersFrom1to5()
extension String {
//인스턴스의 매서드
//"hi"가 세번 출력됨
func printHelloRepetitions(of times: Int) {
for _ in 0..<times {
print("Hello \(self)!")
}
}
}
"hi".printHelloRepetitions(of times: 3)
구조체(열거형)에서, 자신의 속성을 변경하는 메서드는 mutating키워드 필요
extension Int {
// 기존 메서드와 동일하게, mutating 키워드 필요
mutating func square() {
self = self * self
}
}
var someInt = 3
someInt.square()
someInt // result = 9
// UIColor 기본 생성자
var color = UIColor(red: 0.3, green: 0.5, blue: 0.4, alpha: 1)
// 익스텐션 + 편의생성자 조합
extension UIColor {
convenience init(color: CGFloat) {
// 델리게이트어크로스(자기자신의 init을 가져와서 써야한다)
self.init(red: color/255,
green: color/255,
blue: color/255, alpha: 1)
}
}
struct Point {
var x = 0.0, y = 0.0
// 내가 생성자를 구현했기 때문에 기본생성자, 멤버와이즈 제공X
init(x: Double, y: Double) {
self.x = x
self.y = y
}
}
extension Point {
// 실질적인 편의생성자
init() {
self.init(x: 0, y: 0)
}
}
struct Point {
// 저장속성이 초기화가 되어있고 아무런 생성자를 생성하지 않은경우
var x = 0.0, y = 0.0
// 두가지 생성자가 자동으로 생성이 되어있음
// init()
// init(x: Double, y: Double)
}
// 위와같은 경우에 self.init으로 생성자를 호출하지 않고 생성자를 만드는게 가능
extension Point {
**// 확장에서 생성자를 사용자가 만든다해도**
**// 기본생성자, 멤버와이즈이니셜라이즈 + 내가만든 생성자 3개 제공**
init(num: Double) {
self.x = num
self.y = num
}
}
// 기본값 제공/생성자 구현안함
// 기본 생성자 / 멤버와이즈 생성자가 자동 제공 중
struct Rect {
var origin = Point()
var size = Size()
}
extension Rect {
// 센터값으로 Rect 생성하는 생성자 만들기
// 예외적인 경우
// (저장속성에 기본값 + 본체에 생성자 구현 안한 경우, 여전히 기본생성자/멤버와이즈 생성자 제공)
init(center: Point, size: Size) {
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
// (1) 본체의 멤버와이즈 생성자 호출 방식으로 구현 가능
self.init(origin: Point(x: originX, y: originY), size: size)
// (2) 직접 값을 설정하는 방식으로도 구현 가능
//self.origin = Point(x: originX, y: originY)
//self.size = size
}
}
class Dog {
// 저장속성이 초기화가 되어있다면 기본생성자를 제공해준다
var name: String = "보리"
}
Dog()
struct Dog1 {
// 저장속성이 초기화 되어있다면 기본생성자, 멤버와이즈생성자를 기본제공
var name: String = "보리"
}
Dog1()
Dog1(name: <#String#>)
struct Dog1 {
var name: String = "보리"
var weight: Int = 0
// 없는것만 따로 찍어낼 수 있는 기본생성자 제공
var height: Int
}
Dog1(height: <#Int#>)
Dog1(name: <#String#>, weight: <#Int#>, height: <#Int#>)
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 {
// 음수인지, 0인지, 양수인지
enum Kind {
case negative, zero, positive
}
// 계산 속성으로 구현
var kind: Kind {
switch self {
case 0:
return .zero
case 1...:
return .positive
default:
return .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("")
}
// + + - 0 - 0 +
printIntegerKinds([3, 19, -27, 0, -6, 0, 7])