'static'에 해당되는 글 3건

  1. 2017.06.29 상속
  2. 2017.04.10 Swift에서 Objective-C의 상수 대체제에 관하여
  3. 2012.04.05 C <13>. 변수의 범위

상속

Swift/기본문법 2017.06.29 11:00

상속

스위프트의 상속은 클래스, 프로토콜 등에서 가능합니다. 열거형, 구조체는 상속이 불가능합니다. 스위프트는 다중상속을 지원하지 않습니다.   

이번 파트에서는 클래스의 상속에 대해서 알아봅니다


소스코드



클래스의 상속과 재정의

상속 문법

class 이름: 상속받을 클래스 이름 {
    /* 구현부 */
}



// 기반 클래스 Person
class Person {
    var name: String = ""
    
    func selfIntroduce() {
        print("저는 \(name)입니다")
    }
    
    // final 키워드를 사용하여 재정의를 방지할 수 있습니다
    final func sayHello() {
        print("hello")
    }
    
    // 타입 메서드
    // 재정의 불가 타입 메서드 - static
    static func typeMethod() {
        print("type method - static")
    }
    
    // 재정의 가능 타입 메서드 - class
    class func classMethod() {
        print("type method - class")
    }
    
    // 재정의 가능한 class 메서드라도 
    // final 키워드를 사용하면 재정의 할 수 없습니다
    // 메서드 앞의 `static`과 `final class`는 똑같은 역할을 합니다
    final class func finalCalssMethod() {
        print("type method - final class")
    }
}

// Person을 상속받는 Student
class Student: Person {
    var major: String = ""
    
    override func selfIntroduce() {
        print("저는 \(name)이고, 전공은 \(major)입니다")
    }
    
    override class func classMethod() {
        print("overriden type method - class")
    }
    
    // static을 사용한 타입 메서드는 재정의 할 수 없습니다
//    override static func typeMethod() {    }
    
    // final 키워드를 사용한 메서드, 프로퍼티는 재정의 할 수 없습니다
//    override func sayHello() {    }
//    override class func finalClassMethod() {    }

}


동작 확인

let yagom: Person = Person()
let hana: Student = Student()

yagom.name = "yagom"
hana.name = "hana"
hana.major = "Swift"

yagom.selfIntroduce()
// 저는 yagom입니다

hana.selfIntroduce()
// 저는 hana이고, 전공은 Swift입니다

Person.classMethod()
// type method - class

Person.typeMethod()
// type method - static

Person.finalCalssMethod()
// type method - final class


Student.classMethod()
// overriden type method - class

Student.typeMethod()
// type method - static

Student.finalCalssMethod()
// type method - final class



관련문서

The Swift Programming Language - Inheritance





by yagom

facebook : http://www.facebook.com/yagomSoft

facebook group : https://www.facebook.com/groups/yagom/


p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


↓↓↓ 블로거에게 공감은 큰 힘이 됩니다 ↓↓↓ 

'Swift > 기본문법' 카테고리의 다른 글

옵셔널 체이닝  (2) 2017.07.06
인스턴스의 생성과 소멸  (0) 2017.07.03
상속  (0) 2017.06.29
프로퍼티 - Property  (2) 2017.06.26
클로저 - Closure  (0) 2017.06.22
클래스, 구조체, 열거형 비교  (0) 2017.06.19
Posted by yagom


오늘의 주제

Objective-C의 상수와 스위프트의 상수


안녕하세요 야곰입니다.

Objective-C를 쓰다가 스위프트로 넘어왔을 때 고민되었던 부분 중의 하나인 스위프트의 상수에 관해 이야기해 보려 합니다.


혼자 프로젝트를 진행하다 보면 상수의 필요성을 많이 느낄 수 없을지 모르지만, 누군가 협업을 하게 된다면, 혹은 미래 또는 과거의 나와 협업(?)을 하게 된다면 상수의 필요성을 많이 느끼게 됩니다. 바꾸면 안 되는 데이터를 실수로 바꿔서 난감했던 경험이 없나요? 혹시 그런 적이 있다면 상수의 필요성에 대해서는 많이 공감하실 것으로 생각됩니다.


* 오해가 생길 소지의 표현들이 있어서 처음 발행 이후 조금 수정하였습니다. 좋은 의견 주신 과니님 고맙습니다 :)


사라진 const


사실 저는 Objective-C에서 특별한 경우가 아니면 const를 많이 사용하지 않았습니다(반성).


그런데 스위프트에서는 전역이든 지역이든 데이터를 저장할 공간(변수 또는 상수)에는 var 또는 let을 사용하여 변수인지 상수인지 명확히 명시해 주어야 하므로 상수에 대한 고민을 많이 하게 되었습니다.


사실 지역상수가 필요한 경우에 const 키워드를 쓰는 귀찮음 때문에 상수를 많이 사용하지 않았는데 스위프트에서는 var 또는 let을 선택해야 하는 시간이 조금 걸렸지만, 지금은 큰 시간 들일 필요 없이 자연스럽게 상수를 많이 사용하고 있습니다. 또, 혹시라도 상수로 사용해야 하는 경우임에도 변수로 선언하고 사용한다면 Xcode에서 변수 대신 상수를 사용하는 게 어떻냐는 경고를 보여줍니다. 




[Xcode의 경고]


지역상수


지역상수를 사용하는 경우에는 사실 Objective-C와 크게 다를 바 없이 사용할 수 있습니다. 상수의 이름을 지어주는 명명법도 크게 다를 바 없습니다. 

상수로 사용할 변수 앞에 const를 붙여 쓴 것처럼 let을 사용하여 상수를 선언하여 사용하면 됩니다.



// Objective-C
const NSInteger someConstant = 100;


// Swift
let someConstant: Int = 100



전역상수


전역상수를 사용할 때 조금 더 생각해보아야 할 것들이 있습니다. 저는 처음 스위프트를 사용할 때 별생각 없이 Objective-C에서 사용하던 것과 같은 명명법으로 전역상수를 사용했습니다.


// Objective-C NSInteger const  YGSomeGlobalConstant = 100;


// Swift
let YGSomeGlobalConstant: Int = 100


그런데 Objective-C에서 'YG'와 같이 접두어(prefix)를 붙이는 것은 Objective-C에는 네임스페이스(name space)가 없기 때문인데, 스위프트에는 이 단점을 극복했다는 것에 대한 생각이 문득 스쳤습니다.


Objective-C에는 네임스페이스가 없어서 전역변수를 선언하고 사용할 때 꽤 골치가 아팠습니다. 귀찮기도 아주 귀찮았죠. 이름도 매우 길어지기만 했습니다. 열거형(enum)은 정수밖에 지원하지 않기 때문에 다른 타입의 값들은 관련된 상수끼리 묶어 쓰기도 어렵기도 했지요.


// Objective-C의 상수들... // 네임스페이스가 없기 때문에 // 연관된 상수들을 접두어를 사용하여 표현합니다 // 요일 상수들 NSString *const YGWeekMonday = @"MON"; NSString *const YGWeekTuesday = @"TUE"; NSString *const YGWeekWednesday = @"WED"; NSString *const YGWeekThursday = @"THU"; NSString *const YGWeekFriday = @"FRI"; NSString *const YGWeekSaturday = @"SAT"; NSString *const YGWeekSunday = @"SUN"; // 네트워킹 관련 상수들 NSTimeInterval const YGNetworkingTimeoutInterval = 10.0f; NSUInteger const YGNetworkingMaxRetryCount = 3; NSString *const YGNetworkingBaseURLString = @"https://abc.com";


정말 보기만 해도 정신이 없습니다. 또, 실수로 복사 붙여넣기를 하다가 중복된 값을 넣었다면 컴파일 오류가 발생하지 않기 때문에 실수를 찾아내기도 매우 어려워집니다.


스위프트에서는 이런 전역 상수들을 조금 더 멋진 방법으로 표현해 볼 수 있습니다. 타입 내부에 다른 타입을 정의하는 방법으로 네임스페이스를 사용할 수 있습니다. 더군다나 네임스페이스 덕분에 접두어는 더 이상 스위프트에서 사용하지 않습니다.


// Week라는 구조체 타입 내부에
// 여러 타입 상수를 선언
struct Week {
    static let mon: String = "MON"
    static let tue: String = "TUE"
    static let wed: String = "WED"
    static let thu: String = "THU"
    static let fri: String = "FRI"
    static let sat: String = "SAT"
    static let sun: String = "SUN"
}

// 실제 사용시 Week.mon // "MON" Week.sat // "SAT"


처음에 이렇게 선언해 보았습니다. 그런데 만약 복사 붙여넣기를 하다가 실수로 중복된 값을 넣는다면...? 가령 "SUN"을 넣어야 하는데 "SAT"를 넣어버렸다면? 이때는 중복 값이 들어있는지 확인할 수 없습니다. 물론 의도적으로 다른 이름의 상수에 같은 값을 넣을 수도 있지만 그렇지 않은 경우에는 낭패입니다.


그래서 이렇게 개선해 봅니다.


// 열거형의 연관 값(associated value)을 사용하여
// 상수처럼 사용
enum Week: String {
    case mon = "MON"
    case tue = "TUE"
    case wed = "WED"
    case thu = "THU"
    case fri = "FRI"
    case sat = "SAT"
    case sun = "SUN"
}

// 실제 사용시 Week.mon.rawValue // "MON" Week.sat.rawValue // "SAT"



이렇게 사용하면 열거형 내부의 연관 값이 중복되는 경우에 컴파일오류가 발생하게 됩니다. 그래서 미리 실수를 발견하기도 좋습니다.


또, 위의 Objective-C로 선언했던 네트워킹 관련 상수를 스위프트에서 선언한다면 이렇게 바꿔볼 수 있을 것 같습니다.


// Objective-C NSTimeInterval const YGNetworkingTimeoutInterval = 10.0f; NSUInteger const YGNetworkingMaxRetryCount = 3; NSString *const YGNetworkingBaseURLString = @"https://abc.com";
// 사용 YGNetworkingTimeoutInterval // 10.0


// Swift
struct Networking {
    static let timeoutInterval: TimeInterval = 10.0
    static let maxRetryCount: Int = 3
    static let baseURL: URL? = URL(string: "https://abc.com")
}

// 사용

Networking.timeoutInterval // 10.0


이처럼 꼭 열거형의 연관 값을 사용하지 않고 용도에 맞게 구조체의 타입 상수(static let)로 사용해도 좋습니다. 


상수뿐만 아니라 전역변수, 전역함수(메서드) 등에도 충분히 응용할 수 있습니다.


또한 구조체 내부에 다른 타입(구조체, 클래스, 열거형) 등등 몇 단계를 걸쳐 내부 타입을 정의할 수 있기 때문 연관된 값을 타입의 타입의 타입까지 여러 번에 걸쳐 정의도 가능합니다.



struct CalendarItem {
    typealias Year = Int
    typealias Day = Int
    
    enum Week: String {
        case mon = "MON", tue = "TUE" //...
    }
    
    enum Month: Int {
        case jan = 1, feb, mar //...
    }
    
    static let startYear: Int = 1970
    static let startMonth: CalendarItem.Month = .jan
    
    struct Date {
        var day: Day = 1
        var weekDay: CalendarItem.Week = .mon
        var month: CalendarItem.Month = .jan
        var year: Year = CalendarItem.startYear
    }
}

var userBirthday: CalendarItem.Date userBirthday = CalendarItem.Date.init(day: 10, weekDay: .tue, month: .mar, year: 2017)



마치며


같은 Cocoa 플랫폼 위에서 코드를 작성하는데도 불구하고 역시나 언어의 특성을 살려 새로이 구조를 설계하기는 쉽지 않습니다 하핳


무언가 두서없이 써내려간 느낌입니다만, 잘 이해가 가지 않거나 궁금한 점이 있다면 댓글 남겨주세요 :D





by yagom

facebook : http://www.facebook.com/yagomSoft

facebook group : https://www.facebook.com/groups/yagom/


p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


Posted by yagom

C <13>. 변수의 범위

C 2012.04.05 12:30

오늘의 주제

1. 변수의 범위 


열 세번째 시간입니다.^^

지난 번에는 함수에 대해 알아보았어요~
함수... 중요합니다 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
내가 안중요하다고 하는거 있었나..ㅋㅋㅋㅋㅋㅋㅋ
그말인 즉슨 알짜배기 열심히 적고있다는 얘기겠지요?ㅋㅋ

자 그럼 서론 생략하고 변수의 범위에 대해 알아봅시다~
스따뚜~~~~~~~~~~~~


# 변수의 범위

그전에 변수란...?
이미 예전에 포스팅 했지요?ㅎㅎ
잘 기억이 안나신다면...ㅋㅋ
보고옵시다~
2011/12/02 - [C] - C <3>. 변수. Variable

자. 변수에도 범위가 있나요??

오홍 그럼요~

어디서든지 쓸 수 있는녀석, 어떤 곳에서만 쓸 수 있는 녀석 등등 변수가 미치는 범위는 다양하답니다~
변수 뿐만 아니라 함수도 마찬가지예요~^^
그럼 자세히 알아봅시다~

일단 변수에는, 어떤 영역 안에서만 사용 가능한 변수, 한 코드파일 안에서 사용 가능한 변수, 다른 파일에서도 사용 가능한 변수... 등등 이렇게 여러가지가 있어요~

몇몇 변수들은 변수 앞에 붙는 키워드에 따라 분류할 수 있습니다.

extern, static 등등 이런 키워드 들이예요~

자, 아래 설명을 봅시다.

전역변수 (Global 변수) : 어떠한 한 코드 파일 내에서 어디서든지 사용 가능한 변수를 말합니다.
지역변수 (Local 변수) : 어떠한 한 구문 또는 함수 내에서만 사용 가능한 변수를 말합니다.
외부변수 (Extern 변수) : 다른 코드 파일에서도 사용 가능한 변수를 말합니다.
정적변수 (Static 변수) : 한 번 선언이 되면 변수가 사용 가능한 영역을 벗어나도 메모리에 기억되어 사라지지 않는 변수를 말합니다. 

자, 이렇게만 말하니까 이해가 잘 안가시죠?

직접 실습해 봅시다~

일단은 지난번에 생성한 VarAndFunc.h 파일로 갑니다.

네모 박스처럼 이쁘게 코딩 해 줍니다~


자, 그럼 이제 FuncExample.h로 가서 VarAndFunc.h에서 선언했던 녀석들을 한 번 불러와 볼게요~
extern 이라는 녀석이 외부 변수를 뜻하는 겁니다.


보시다시피, extern 키워드를 써서 다른 코드파일(VarAndFunc.h)에서 변수와 함수를 가져오는 것을 볼 수 있죠?
이렇게 하면 다른 파일에 선언된 변수를 가져와서 쓸 수 있습니다. 
main함수에서도 새로 몇 줄 추가를 합니다. 


이렇게 추가를 해주고, 우리가 만들어 주었던 myFirstFunction 함수로 와서 static(정적)변수를 선언해 줍니다.
이녀석은 함수가 끝나고 메모리에서 지워지지 않습니다.
무슨말이냐 하면... 우리가 흔히 사용하던 int 변수는 함수가 끝나면 초기화가 되고 함수를 다시 시작하여 선언하면 다시 생성됩니다.
이것을 지역변수라고 합니다.
하지만 static 변수를 선언하게 되면 다시 함수를 호출하여도 초기화가 되지 않고 지난 값들을 기억하고 있다가 다시 그 값을 불러들이게 됩니다.
잘 이해가 안가신다면 밑에 실행 결과를 봅시다~

[##_http://blog.yagom.net/script/powerEditor/pages/1C%7Ccfile29.uf@1413BC424F707BEE1A67DE.png%7Cwidth=%22601%22%20height=%22118%22%20alt=%22%22%20filename=%224.png%22%20filemime=%22image/jpeg%22%7C_##]


짜잔~
static 변수는 함수를 몇 번 호출하더라도, 한 번 선언을 했으면 지워지지 않고 초기화 하는 1은 신경을 쓰지 않습니다.
하지만 지역변수인 녀석은 계속 1로 초기화 되기 때문에 1만 출력이 되죠.
또한 global 변수는 하나의 함수 안에 종속되지 않고 나하의 코드 파일 안에서 어디서든지 사용 할 수 있습니다.
그리고 extern 변수는 다른 파일에서 가져와서 쓸 수 있는거죠.


잘 이해가 되셨는지 모르겠습니다만...

저도 지금 감기는 눈으로 휘갈기는거라...ㅋㅋㅋ

혹시 이해가 가지 않는 부분이나 틀린 부분이 있으면 날카롭게 지적 부탁드립니다...^^

그럼 야곰은 이만 물러갑니다..^^



by yagom

twitter : @yagomsoft

 
p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


↓↓↓저 열심히 썼는데 추천 한방 꾹 눌러주고 가시는 건 어떨까요? ^~^ 사랑합니다~ ↓↓↓ 



'C' 카테고리의 다른 글

C <15>. 전처리자  (0) 2012.05.14
C <14>. 배열  (4) 2012.05.11
C <13>. 변수의 범위  (0) 2012.04.05
C <12>. 함수  (4) 2012.04.02
C <11>. 포인터 (2)간단실습  (0) 2012.03.27
C <10>. 포인터 (1)개념잡기  (3) 2012.03.23
Posted by yagom


티스토리 툴바