상속

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

Class vs Struct/Enum

소스코드


열거형과 구조체는 값 타입이며, 클래스는 참조 타입이라는 것이 가장 큰 차이입니다. 또한, 클래스는 상속이 가능하지만 구조체와 열거형은 상속이 불가능합니다.

struct ValueType {
    var property = 1
}

class ReferenceType {
    var property = 1
}

// 첫 번째 구조체 인스턴스
let firstStructInstance = ValueType()
// 두 번째 구조체 인스턴스에 첫 번째 인스턴스 값 복사
var secondStructInstance = firstStructInstance
// 두 번째 구조체 인스턴스 프로퍼티 값 수정
secondStructInstance.property = 2

// 두 번째 구조체 인스턴스는 첫 번째 구조체를 똑같이 복사한 
// 별도의 인스턴스이기 때문에 
// 두 번째 구조체 인스턴스의 프로퍼티 값을 변경해도
// 첫 번째 구조체 인스턴스의 프로퍼티 값에는 영향이 없음
print("first struct instance property : \(firstStructInstance.property)")    // 1
print("second struct instance property : \(secondStructInstance.property)")  // 2


// 클래스 인스턴스 생성 후 첫 번째 참조 생성
let firstClassReference = ReferenceType()
// 두 번째 참조 변수에 첫 번째 참조 할당
let secondClassReference = firstClassReference
secondClassReference.property = 2

// 두 번째 클래스 참조는 첫 번째 클래스 인스턴스를 참조하기 때문에
// 두 번째 참조를 통해 인스턴스의 프로퍼티 값을 변경하면
// 첫 번째 클래스 인스턴스의 프로퍼티 값을 변경하게 됨
print("first class reference property : \(firstClassReference.property)")    // 2
print("second class reference property : \(secondClassReference.property)")  // 2


관련문서

The Swift Programming Language - Enumerations

The Swift Programming Language - Classes and Structures





by yagom

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

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


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

RSS Feed 받기   


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


저작자 표시 비영리 변경 금지
신고

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

프로퍼티 - Property  (2) 2017.06.26
클로저 - Closure  (0) 2017.06.22
클래스, 구조체, 열거형 비교  (0) 2017.06.19
열거형 - Enumerations  (0) 2017.06.15
클래스  (0) 2017.06.12
구조체  (2) 2017.06.08
Posted by yagom

클래스

Swift/기본문법 2017.06.12 11:00

클래스


소스코드


정의 문법

클래스는 참조 타입입니다. 타입이름은 대문자 카멜케이스를 사용하여 정의합니다.

class 이름 {
	/* 구현부 */
}


프로퍼티 및 메서드 구현

클래스의 타입 메서드는 두 종류가 있습니다. 상속 후 재정의가 가능한 class 타입메서드, 상속 후 재정의가 불가능한 static 타입메서드가 있습니다. 자세한 내용은 상속 부분에서 다시 다룹니다.

class Sample {
    // 가변 프로퍼티
    var mutableProperty: Int = 100 

    // 불변 프로퍼티
    let immutableProperty: Int = 100 
    
    // 타입 프로퍼티
    static var typeProperty: Int = 100 
    
    // 인스턴스 메서드
    func instanceMethod() {
        print("instance method")
    }
    
    // 타입 메서드
    // 재정의 불가 타입 메서드 - static
    static func typeMethod() {
        print("type method - static")
    }
    
    // 재정의 가능 타입 메서드 - class
    class func classMethod() {
        print("type method - class")
    }
}


클래스 사용

// 인스턴스 생성 - 참조정보 수정 가능
var mutableReference: Sample = Sample()

mutableReference.mutableProperty = 200

// 불변 프로퍼티는 인스턴스 생성 후 수정할 수 없습니다
// 컴파일 오류 발생
//mutableReference.immutableProperty = 200


// 인스턴스 생성 - 참조정보 수정 불가
let immutableReference: Sample = Sample()

// 클래스의 인스턴스는 참조 타입이므로 let으로 선언되었더라도 인스턴스 프로퍼티의 값 변경이 가능합니다
immutableReference.mutableProperty = 200

// 다만 참조정보를 변경할 수는 없습니다
// 컴파일 오류 발생
//immutableReference = mutableReference

// 참조 타입이라도 불변 인스턴스는 
// 인스턴스 생성 후에 수정할 수 없습니다
// 컴파일 오류 발생
//immutableReference.immutableProperty = 200


// 타입 프로퍼티 및 메서드
Sample.typeProperty = 300
Sample.typeMethod() // type method

// 인스턴스에서는 타입 프로퍼티나 타입 메서드를
// 사용할 수 없습니다
// 컴파일 오류 발생
//mutableReference.typeProperty = 400
//mutableReference.typeMethod()


학생 클래스 만들어보기

class Student {
	// 가변 프로퍼티
    var name: String = "unknown"

    // 키워드도 `로 묶어주면 이름으로 사용할 수 있습니다
    var `class`: String = "Swift"
    
    // 타입 메서드
    class func selfIntroduce() {
        print("학생타입입니다")
    }
    
    // 인스턴스 메서드
    // self는 인스턴스 자신을 지칭하며, 몇몇 경우를 제외하고 사용은 선택사항입니다
    func selfIntroduce() {
        print("저는 \(self.class)반 \(name)입니다")
    }
}

// 타입 메서드 사용
Student.selfIntroduce() // 학생타입입니다

// 인스턴스 생성
var yagom: Student = Student()
yagom.name = "yagom"
yagom.class = "스위프트"
yagom.selfIntroduce()   // 저는 스위프트반 yagom입니다

// 인스턴스 생성
let jina: Student = Student()
jina.name = "jina"
jina.selfIntroduce() // 저는 Swift반 jina입니다




관련문서

The Swift Programming Language - Classes and Structures





by yagom

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

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


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

RSS Feed 받기   


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

저작자 표시 비영리 변경 금지
신고

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

클래스, 구조체, 열거형 비교  (0) 2017.06.19
열거형 - Enumerations  (0) 2017.06.15
클래스  (0) 2017.06.12
구조체  (2) 2017.06.08
옵셔널  (0) 2017.06.05
반복문  (0) 2017.06.01
Posted by yagom


오늘의 주제

1. 구조체
2. 클래스



안녕하세요, 야곰입니다. 


지난 포스팅에서는 스위프트의 함수와 함께 스위프트에서 제공하는 컬렉션 타입에 대해 알아봤습니다.


2017/01/23 - [Swift] - Swift란 어떤 언어인가?

2017/01/25 - [Swift] - Swift 기초문법 - 변수, 상수, 기초 데이터 타입

2017/02/06 - [Swift] - Swift - 함수, 콜렉션 타입



이번에는 스위프트의 구조체와 클래스에 대해 알아보겠습니다 :)


구조체와 클래스

구조체와 클래스는 프로그래머가 데이터를 용도에 맞게 묶어 표현하고자 할 때 용이합니다. 구조체와 클래스는 프로퍼티와 메서드를 사용하여 구조화된 데이터와 기능을 가질 수 있습니다. 하나의 새로운 사용자정의 데이터 타입을 만들어 주는 것입니다. 


객체지향 프로그래밍 패러다임을 알고 있다면 클래스라는 용어를 들어봤을 겁니다. 객체지향 프로그래밍 패러다임이 아니더라도 데이터를 구조화하여 관리하는 데 구조체를 사용해봤을 겁니다. 스위프트에서는 구조체와 클래스의 모습과 문법이 거의 흡사합니다. 다만, 구조체의 인스턴스는 값 타입이고, 클래스의 인스턴스는 참조 타입이라는 것이 이 둘을 구분하는 가장 큰 차이점입니다. 


이제까지 우리가 알아본 스위프트의 데이터 타입과 열거형은 모두 값 타입니다. 그러나 구조체와 함께 배워볼 클래스는 참조 타입입니다. C 언어와 Objective-C의 포인터와 유사한 개념입니다. 


참고로 스위프트는 참조 타입보다는 값 타입에 친절한 언어입니다.



구조체


구조체는 struct 키워드로 정의합니다.


구조체 명명법



struct [구조체 이름] { [프로퍼티와 메서드들] }


아래에 사람의 기본 정보를 구성하는 구조체를 정의해봤습니다. BasicInformation 이라는 이름으로 정의했으며 이 구조체는 String 타입인 name과 Int 타입인 age라는 저장 프로퍼티를 가집니다.

struct BasicInformation {
    var name: String
    var age: Int
}


구조체 인스턴스의 생성 및 초기화


구조체 정의를 마친 후, 구조체의 인스턴스를 생성하고 초기화하고자 할 때에는 기본적으로 생성되는 멤버와이즈 이니셜라이저를 사용합니다. 구조체에 기본 생성된 이니셜라이저의 매개변수는 구조체의 프로퍼티 이름으로 자동 지정됩니다. 
인스턴스가 생성되고 초기화된 후 프로퍼티 값에 접근하고 싶다면 마침표(.)를 사용하면 됩니다. 구조체를 상수 let으로 선언하면 인스턴스 내부의 프로퍼티 값을 변경할 수 없고, 변수 var로 선언하면 내부의 프로퍼티가 var로 선언된 경우에 값을 변경해줄 수 있습니다. 

// 프로퍼티 이름(name, age)으로 자동 생성된 이니셜라이저를 사용하여 구조체를 생성합니다. var yagomInfo: BasicInformation = BasicInformation(name: "yagom", age: 99) yagomInfo.age = 100 // 변경 가능! yagomInfo.name = "Bear" // 변경 가능! // 프로퍼티 이름(name, age)으로 자동 생성된 이니셜라이저를 사용하여 구조체를 생성합니다. let hanaInfo: BasicInformation = BasicInformation(name: "hana", age: 99) hanaInfo.age = 100 // 변경 불가!


클래스

클래스를 어떻게 정의하고 클래스의 인스턴스를 어떻게 생성하는지 그리고 클래스를 어떻게 활용하는지에 대해 알아보겠습니다. 스위프트의 클래스는 부모클래스가 없더라도 상속 없이 단독으로 정의가 가능합니다. 

클래스 명명법


클래스를 정의할 때에는 class라는 키워드를 사용합니다. 

class [클래스 이름] { 
	[프로퍼티와 메서드들]
} 
클래스를 정의하는 방법은 구조체와 흡사합니다. 다만, 클래스는 상속받을 수 있기 때문에 상 속받을 때에는 클래스 이름 뒤에 콜론(:)을 써주고 부모클래스 이름을 명시합니다. 
class [클래스 이름]: [부모클래스 이름] { 
	[프로퍼티와 메서드들]
}
사람의 기본정보를 프로퍼티로 갖는 클래스를 정의해보겠습니다.

class Person {
    var height: Float = 0.0
    var weight: Float = 0.0
}
위에 정의된 클래스는 Float 타입인 height와 weight 저장 프로퍼티가 있는 Person 클래스입니다. 

클래스 인스턴스의 생성과 초기화


클래스를 정의한 후, 클래스의 인스턴스를 생성하고 초기화하고자 할 때에는 기본적인 이니셜라이저를 사용합니다. 위 코드의 Person 클래스에서는 프로퍼티의 기본값이 지정되어 있으므로 전달인자를 통하여 따로 초깃값을 전달해주지 않아도 됩니다. 
인스턴스가 생성되고 초기화된 후(이니셜라이즈된 후) 프로퍼티 값에 접근하고 싶다면 마침표(.)를 사용하면 됩니다. 구조체와는 다르게 클래스의 인스턴스는 참조 타입이므로 클래스의 인스턴스를 상수 let으로 선언해도 내부 프로퍼티 값을 변경할 수 있습니다. 구조체 코드와 클래스 코드를 비교해보세요.

var yagom: Person = Person() yagom.height = 123.4 yagom.weight = 123.4 let hana: Person = Person() hana.height = 123.4 hana.weight = 123.4


클래스 인스턴스의 소멸


클래스의 인스턴스는 참조 타입이므로 더는 참조할 필요가 없을 때 메모리에서 해제됩니다. 이 과정을 소멸이라고 칭하는데 소멸되기 직전 deinit라는 메서드가 호출됩니다. 클래스 내부에 deinit 메서드를 구현해주면 소멸되기 직전 deinit 메서드가 호출됩니다. 이렇게 호출 되는 deinit 메서드는 디이니셜라이저(Deinitializer)라고 부릅니다. deinit 메서드는 클래스당 하나만 구현할 수 있으며, 매개변수와 반환 값을 가질 수 없습니다. deinit 메서드는 매개변수를 위한 소괄호도 적어주지 않습니다. 또, 프로그래머가 직접 deinit 메서드를 호출할 수도 없습니다. 아래 코드에서 Person 클래스에 구현된 deinit 메서드 를 확인할 수 있습니다.

class Person { var height: Float = 0.0 var weight: Float = 0.0 deinit { print("Person 클래스의 인스턴스가 소멸됩니다.") } } var yagom: Person? = Person() yagom = nil // Person 클래스의 인스턴스가 소멸됩니다.

보통 deinit 메서드에는 인스턴스가 메모리에서 해제되기 직전에 처리할 코드를 넣어줍니다. 예를 들어 인스턴스 소멸 전에 데이터를 저장한다거나 다른 객체에 인스턴스 소멸을 알려야 할 때는 특히 deinit 메서드를 구현해야 합니다. 


구조체와 클래스의 차이

구조체와 클래스는 서로 비슷하거나 같은 점도 많습니다. 다음은 같은 점입니다. 
  • 값을 저장하기 위해 프로퍼티를 정의할 수 있습니다. 
  • 기능 수행을 위해 메서드를 정의할 수 있습니다. 
  • 서브스크립트 문법을 통해 구조체 또는 클래스가 가지는 값(프로퍼티)에 접근하도록 서브스크립트를 정의할 수 있습니다. 
  • 초기화될 때의 상태를 지정하기 위해 이니셜라이저를 정의할 수 있습니다. 
  • 초기구현과 더불어 새로운 기능 추가를 위해 익스텐션을 통해 확장할 수 있습니다. 
  • 특정 기능을 수행하기 위해 특정 프로토콜을 준수할 수 있습니다. 


그러나 확연히 다른 점도 존재합니다. 
  • 구조체는 상속할 수 없습니다.
  • 타입캐스팅은 클래스의 인스턴스에만 허용됩니다.
  • 디이니셜라이저는 클래스의 인스턴스에만 활용할 수 있습니다.
  • 참조 횟수 계산(Reference Counting)은 클래스의 인스턴스에만 적용됩니다. 


구조체와 클래스는 겉보기엔 정의하는 방법도, 인스턴스화하는 방법도, 프로퍼티와 메서드를 갖는다는 점을 비롯해 많은 부분에서 비슷해보입니다. 그러나 이 두 타입을 구분 짓는 가장 큰 차이점은 값 타입과 참조 타입이라는 것입니다. 그래서 참조 횟수 계산은 클래스의 인스턴스에만 해당됩니다. 




스위프트의 기본 데이터 타입은 모두 구조체

public struct String { /// An empty 'String'. public init() }

위의 코드는 스위프트 표준 라이브러리에 포함되어 있는 스위프트의 String 타입의 기본 정의 코드입니다. public은 잠시 제쳐두고, struct 키워드는 익숙하지 않으신가요? 네, 스위 프트의 다른 기본 타입(Bool, Int, Array, Dictionary, Set 등등)도 String 타입과 마찬 가지로 모두 구조체로 구현되어 있습니다. 그렇다는 의미는, 기본 데이터 타입은 모두 값 타입 이라는 뜻입니다. 전달인자를 통해 데이터를 전달하면 모두 값이 복사되어 전달될 뿐, 함수 내부에서 아무리 전달된 값을 변경해도 기존의 변수나 상수에는 전혀 영향을 미치지 못한다는 의미입니다. 이런 점을 더욱 확실히 하기 위해 스위프트의 전달인자는 모두 상수로 취급되어 전달되는 것일지도 모릅니다. 


구조체와 클래스 선택해서 사용하기 

구조체와 클래스는 모두 새로운 데이터 타입을 정의하고 기능을 추가한다는 점에서는 같습니다. 하지만 구조체 인스턴스는 항상 값 타입이고, 클래스 인스턴스는 참조 타입입니다. 그 의미는 생긴 것은 비슷하지만 용도는 다르다는 의미입니다. 프로젝트의 성격에 따라, 데이터의 활용 용도에따라, 특정타입을 구현할 때 구조체와 클래스 둘 중 하나를 선택해서 사용해야 합니다. 
애플은 가이드라인에서 다음 조건 중 하나 이상에 해당된다면 구조체를 사용하기를 권합니다. 
  • 연관된 간단한 값의 집합을 캡슐화 하는 것만이 목적일 때 
  • 캡슐화된 값이 참조되는 것보다 복사되는 것이 합당할 때
  • 구조체에 저장된 프로퍼티가 값 타입이며 참조되는 것보다 복사되는 것이 합당할 때
  • 다른 타입으로부터 상속받거나 자신이 상속될 필요가 없을 때 

구조체로 사용하기에 가장 적합한 예로는 좌표계가 있습니다. x, y 좌표 등을 표현하고 싶을 때 Int 타입으로 x, y 프로퍼티를 가질 수 있으며, 물건의 크기를 표현하고자 할 때는 부동소수 표현인 Double 또는 Float 타입을 사용하여 width, height, depth 등으로 묶어 표현해 줄 수 있습니다. 
이런 몇 가지 상황을 제외하면 클래스로 정의하여 사용합니다. 대다수 사용자정의 데이터 타입은 클래스로 구현할 일이 더 많을 수 있습니다. 

이번에 스위프트의 구조체와 클래스에 대해 알아봤습니다. 다음 포스팅에서는 프로토콜과 익스텐션에 대해 알아보겠습니다. 
다음 번에 또 뵈어요~ 고맙습니다 :D




by yagom

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

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

twitter : http://www.twitter.com/yagomSoft ( @yagomsoft )

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

RSS Feed 받기   



저작자 표시 비영리 변경 금지
신고

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

스위프트 시작하기  (0) 2017.05.08
Swift - 프로토콜, 익스텐션  (0) 2017.03.07
Swift - 구조체 클래스  (0) 2017.02.28
Swift - 함수, 콜렉션 타입  (0) 2017.02.06
Swift 기초문법 - 변수, 상수, 기초 데이터 타입  (0) 2017.01.25
Swift란 어떤 언어인가?  (0) 2017.01.23
Posted by yagom



오늘의 주제

1. 상속의 개념 


아홉번째 시간입니다.^^

Objective-C는 정말 오랜만이네요..^^

초코찌찌님의 요청으로 새로운 개념을 하나 가지고 왔습니다~

지난 번에는 메소드에 대해 알아보았습니다~
이번에는 클래스의 상속에 대해 알아보도록 합니다.^^

이 포스팅은 지난 

2012/01/30 - [Objective-C] - Objective C <5>. 클래스와 객체(인스턴스)<1>

2012/02/05 - [Objective-C] - Objective C <6>. 클래스와 객체(인스턴스)<2>

이 두개의 포스팅 지식을 필요로 합니다~

다 알고 계신가요?ㅎ

그렇다면 고고고고고고고고~~~~~~무비무비무비~~~~~~


# 상속이란?

상속이란 무엇일까요?

저는 쉽게 한마디로 말하면, 클래스의 확장 이라고 표현하고 싶네요.

즉, 이미 만들어져 있는 클래스에서 내가 원하는 부분을 추가하거나 변경하여 새로운 클래스를 생성할 수 있습니다.
 
하지만 여기에도 규칙이 있기 마련이죠..^^

상속에서는 부모클래스와 자식 클래스라는 개념을 가지고 말을 합니다.

자식 클래스는 부모 클래스를 상속 받는다고 표현합니다.

상속 받는다는 것은 원래 클래스에 추가나 변경을 한다고 말씀드렸죠?

그렇다면 부모클래스와 자식 클래스 중에 더 확장된 클래스는 무엇일까요?

네, 바로 자식 클래스이죠~

부모클래스 보다 자식 클래스가 더 덩치가 크다 이말입니다^^ (사실 그렇지 않을 수도 있습니다만, 개념상 편하게 이렇다고 합시다 ㅎ)

그림에서 보다시피 부모가 자식에게 자신의 대부분의 것을 물려줍니다.


자식은 물려받은 그것들에서 마음에 들지 않는 것이 있으면 바꾸기도 하고, 더 필요한 것이 있으면 추가하기도 합니다.

자 대충 감이 오시나요?

상속을 받게되면 부모 클래스의 헤더에 선언된 메소드와 변수가 자식에게 상속됩니다.
물론 모두 상속되는 건 아닙니다. 부모클래스에서 상속해주지 않겠다고 선언해 준 녀석이 있다면 그 녀석들은 상속되지 않습니다.

그럼 실질적으로 상속이 어떻게 되는지 한 번 볼까요?

아래 그림을 보면, 우리가 만들었던 클래스 입니다.
이 클래스를 만들때 대화상자에서 Sub class of... NSObject라고 했던 것 기억하시려나 모르겠습니다^^
지금 MyFirstClass.h 헤더파일을 보게되면 MyFirstClass는 NSObject를 상속받았음이 명시되어 있습니다.
그렇습니다. 모든 Objective-C의 class들은 기본적 NSObject를 상속받고 있습니다.
아래 그림처럼 직접적으로 받던지, 아니면 우리가 다음에 새로 만들어볼 MyFirstClass의 자식클래스처럼 다른 클래스를 거쳐 상속을 받던지간에 어찌되었든 상속을 받습니다.

자, 그럼 이 NSObject라는 녀석을 한 번 살표볼까요?

NSObject 에서 오른쪽 버튼 클릭을 하여 Jump to Definition로 향합니다^^

그러면 Foundation framework에 포함된 NSObject.h 파일에서 NSObject의 선언부를 볼 수 있습니다.

NSObject에 이런저런 많은 메소드들이 선언되어있네요^^

우리가 어떤 인스턴스를 만들어 줄 때, alloc , init 해줬던 것을 기억하시나요?ㅎ

고녀석들 요기있네요~~~~~~~~~ㅎㅎㅎ 말씀드렸듯이 모든 클래스들은 NSObject를 상속받기 때문에 어디서든지 alloc, init을 할 수 있는 것입니다.


# 상속 실습해보기

자, 대충 개념은 잡았겠다, 실습 한 번 들어가 봅시다 ㅎ

새로운 클래스를 만들기 위하여 New File... 합니다!


Cocoa의 Objective-C class를 선택해 주시고 Next~

자, 그 후에 여기서!! Subclass of MyFirstClass를 해 주는 겁니다!!

MyFirstClass를 상속 받겠다는 의미가 되겠습니다!!

그 후에 클래스명을 FirstChildClass로 합니다.

FirstChildClass.h로 이동해 봅니다.

MyFirstClass를 상속하고 있다고 명기되어 있습니다. 정말 딱 이거 하나 있는데 이 클래스에서 어떤일이 벌어졌을까요?ㅎㅎㅎ

심지어 구현부도 텅텅 비어있는 멍텅구리 같아 보입니다 ㅎㅎㅎ

자, 하지만 우리는 상속받고 있다는 것을 알기 때문에, 무작정 뭔가를 시도해 봅시다~

열시미 타이핑타이핑 ~_~ 자세한 소스 설명은 주석에 담겨있지요?ㅎ

짜잔~~~~~~~ 실행 결과입니다.

분명히 자식클래스는 속이 텅텅 비어있는 녀석 같아보였는데, 부모클래스에서 이미 만들어져 있는 메소드와 변수를 사용할 수 있었습니다.

캬~ 우리 모두 정말 부모님께 감사해야 합니다...ㅋㅋ


여하간 이것으로 상속에 대한 개념을 좀 알아봤습니다. 횡설수설이라 이해가 잘 되실지는 모르겠네요ㅠ_ㅠ

혹여나 이해가 되지 않는 부분 또는 잘못된 점이 있다면 댓글 부탁드립니다~^^

그럼 뿅!!!!!!!!!!!!!


by yagom

twitter : @yagomsoft

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

RSS Feed 받기   


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


저작자 표시 비영리 변경 금지
신고
Posted by yagom

오늘의 주제

1. Class 만들어보기 
2. Class Method, Getter, Setter, Instance Method... 



여섯 번째 시간입니다.^^

지난 번에클래스와 인스턴스에 관한 개요를 알아보았습니다.
하지만, 말로만 듣고는 잘 감이 안오시지요?
물론 이번 포스팅을 보아도 아리송 하실 수 있습니다.
정말 짧은 코드이지만 많은 내용이 담겨져 있으니 이번 포스팅도 보고 또 보셔야 할 듯 합니다^^
정말 중요한 것이니 몇 번을 보고, 다른 싸이트를 검색하고, 직접 계속 둘러보면서 꼭 몸으로 익히도록 하세요~!

자 그럼 오늘은 직접 클래스를 한 번 만들어 보도록 합시다~
출바알~~~~~~~~~~~~


# Class 만들어 보기


자... 새로운 프로젝트를 만들고 아래 그림처럼 새로운 클래스 생성을 위해 New File...을 선택합니다~


자, 그 후에는 Objective-C class라는 녀석을 선택 한 후 Next ~!



자, 클래스 이름은 MyFirstClass로 만들어 주겠습니다. Subclass of 란에는 NSObject를 선택해 주세요~


저장경로는 그대로 놔두고 Create~!


자~ 새로운 클래스가 생성되어있습니다!!


# Class Method, getter, setter, Instance Method...

자동으로 생성된 코드를 한 번 봅시다요~
Foundation헤더가 자동으로 import되어있구요~
@interface MyFirstClass : NSObject

@end

이렇게 생성되었네요~
우리 사용자 인터페이스 뭐 이런말 많이 하잖아요? 인터페이스 뭐 감이 오시죠?
클래스의 요모조모를 만들어 줄 수 있는 영역입니다.
@end는 말그대로 끝!
그러니까 저 빈 공백 사이를 우리가 채우게 되면 클래스의 모양을 완성하는 것이라는 느낌이 오지 않나요? 오홍홍
 : NSObject의 뜻은 NSObject의 Subclass라는 이야기 입니다. NSObject를 상속받은 것이지요... 뭐 더 자세한 것은 다음에 설명해 보도록 할게요..^^
 


자 내용을 채워넣어 봅니다...
빨간 네모박스대로 코드를 넣어봅시다..^^  




자~ 이제 코드 설명 들어갑니다~

중괄호 { } 안에 들어가 있는 세 녀석들이 있습니다.
이녀석들을 instance variable 즉, '인스턴스변수'라고 합니다.
지난 번에 설명드렸던 것 중에 틀 안에 클래스마다 가지고 있는 특징들을 저장하는 빈공간들이 있다고 설명드렸을 거예요~
이녀석들이 그 녀석들입니다.
인스턴스는 클래스의 틀을 가지고 만들어 지는 거잖아요? 지금 우리는 클래스 틀을 만드는 중이구요~
그래서 인스턴스가 새로 똻!!!!! 만들어지면 저 세 녀석들을 가지고 태어납니다. 물론 저 세 녀석들은 텅텅 빈 멍텅구리이지요^^
저기 세 녀석들에 뭐가 들어가냐에 따라서 이 인스턴스는 다른녀석들과 겉모양과 틀은 같아도 내용이 다른 인스턴스(객체)가 되는 것이랍니다.
이녀석은 하나의 integer변수와 두개의 string을 가지고 있네요~

중괄호가 닫히고 @property라는 녀석들이 있네요.
이 property와 다음 그림의 구현파일에서 볼 수 있는 @synthesize라는 녀석과 짝을 이루어서 자동으로 접근자 메소드 들을 생성해 주는 역할을 합니다.
말로만 해서는 잘 이해가 안가시죠?ㅎ 접근자(getter, setter)녀석들을 직접 만들어 쓰는게 정말 귀찮거든요..^^ 그것은 이따가 구현파일 보면서 다시 설명해 드리도록 하지요~
그리고 property옆쪽 괄호 안에 들어가 있는 녀석들은 이 변수들을 꺼내 쓰고 집어넣을때 등등 뭐 이녀석들을 어떻게 관리할지 명시해 주는 옵션 같은 녀석들인데요, 지금은 일단 넘어가도록 합시다^^ 이것만 해도 골치아프잖아요~ㅎㅎ 

그 아래에는 메소드들이 명시되어 있는데요, 일단 메소드에 대해 간략하게 이야기 해보자면,
메소드라는 녀석들은 무엇인가를 수행하는 역할을 합니다.
쉽게 설명을 해서 전자레인지는 우리가 차가운 음식을 집어넣고 버튼을 누르면 데워서 뜨거운 음식으로 만들어 줍니다. 즉, 찬음식을 데워서 뜨거운 음식을 만드는 일련의 과정을 수행하는 역할을 하지요.
메소드도 우리가 메소드에게 일할거리를 던져주면 메소드의 고유한 역할들을 수행합니다.
감이 오시나요?ㅎ
여튼, 여기 헤더파일(.h)에서는 이런 메소드가 있다~ 정도만 말해주고, 그녀석들의 역할을 구현파일(.m)에서 명시해 줍니다.


다시 돌아와서 @property아래에보면 - 로 시작하는 메소드 들이 쭈욱 나열되어 있습니다.
요녀석들을 우리는 '인스턴스 메소드'라고 부릅니다.
요녀석들은 클래스라는 틀에서 찍혀 나온 후에만 동작하는 녀석들입니다.
즉, 인스턴스에서만 작동하는 녀석입니다.

그 아래에 보면 +로 시작하는 '클래스 메소드'가 보입니다.
이녀석도 메소드이긴 하지만 좀 독특한 녀석입니다. 클래스라는 틀이 하나의 인스턴스를 찍어내기도 전에 뭔가의 역할을 할 수 있는 녀석입니다.
잘 이해가 안가시죠? 자동차 공장에서 차를 만드는 생산라인에서 뭔가를 할 수 있다... 즉, 만들어지는 차가 아닌 생산라인 자체에서 뭔가를 수행한다는 의미로 받아들이시면 될 듯 합니다. "차 생산을 시작해라!" 라는 명령 같은 것이 되겠죠?ㅎ
그렇다면 자동차안에 있는 고유의 특성들(인스턴스 변수들)은 이 클래스 메소드 안에서 쓰일 수 없겠군요^^

말이 참 어렵지요? 헷갈리기도 무지하게 헷갈리구요...ㅎㅎ

그럼 이제 구현파일로 가서 이 메소드라는 녀석들이 무엇을 하는 녀석들인지 속삭여 줄 때가 되었네요 ㅎ


자, @synthesize라는 녀석은 @property와 짝을 이뤄서 getter와 setter를 자동으로 만들어 준다고 말씀드렸어요~
@property에서는 변수형, 변수명을 모두 명시해 주지만, @synthesize에서는 변수명만 기재해 줍니다.
@property에서 토스~ @synthesize에서 스파이크~ ㅋㅋㅋ 농담입니다~~~~~~

여튼 아래에 보시면 아까 헤더파일에서 정의해 주었던 메소드들이 하는 역할들이 쭈욱 나열되어 있는 것을 볼 수 있으실 거예요~

캡쳐 화면에서 오타가 있습니다.
인스턴스를 설정해 준다. 인스턴스를 반환한다. (x)
인스턴스 변수를 설정해 준다(setter), 인스턴스 변수를 반환한다(getter). (o)

여튼 메소드들의 역할들은 주석으로 설명을 달아놓았으니 대충 짐작하시리라 믿습니다.
그래도 혹시몰라 다시 간략히 설명하자면

호출한다라는 것은 그 메소드에게 일을 명령한다는 것으로 해석하시면 되겠습니다.
즉 myFirstMethod라는 인스턴스 메소드를 호출하면 NSLog를 남기는 역할을 수행하는 것입니다.

다음에 setMySecret:이라는 인스턴스 메소드를 호출하면 mySecret라는 인스턴스 변수에 secret이라는 녀석을 통해 받아온 값을 저장해 주는 역할을 수행합니다. 이러한 형태를 우리는 setter라고 부릅니다. mySecret이라는 녀석을 setting해주는 녀석이라 이말이죠 ㅎ. 메소드에 대해서는 다음번(바로 다음번)에 자세하게 다룰 것이므로 잘 모르겠어도 '이 메소드는 mySecret이라는 녀석에 뭔가를 집어넣는 녀석이구나' 라고 생각하세용~

다음은 mySecret이라는 녀석의 값을 알아보는 메소드 입니다. 메소드 이름도 getMySecret이네요^^
mySecret의 내용을 불러오는 메소드 입니다. 이런 형태의 녀석을 getter라고 하죠~

자, 이렇듯 mySecret이라는 하나의 녀석을 넣고 빼고 하려면 복잡하고 귀찮게 두개의 메소드를 따로 만들어 줘야 하는데, 그 수고를 덜어주는 녀석들이 바로 @property, @synthesize 되겠습니다^^ 조금 감이 오실까요?ㅎ 요~ 밑에 가시면 좀 더 이해가 가실거예요~

마지막으로 itIsClassMethod라는 클래스 메소드가 구현되어 있습니다.
사실 클래스 메소드는 이런 시시한 역할을 하지는 않지만, 예를 들어보기 위해 제가 만들어 본 것입니다..ㅎㅎ
어쨌거나 저쨌거나~ 위에서 말했든 이녀석은 +로 시작을 하므로 클래스 메소드이고, 인스턴스가 되기도 전에 호출이 가능 합니다~
호출하면 로그를 남기는 역할을 수행하는군요~

이렇게 구현파일 탐험이 끝났습니다~ㅎㅎ

그럼 이렇게 만들어진 클래스를 직접 구워 삶아 보아야 겠지요?ㅎ

main구현파일로 가봅시다~!


네, 또 한바탕 타이핑 합니다 ㅎㅎ
참참참, 스크린샷에 빼놓은 부분이 있는데요, #import "MyFirstClass.h" 해주셔야 합니다~
import뒤에 누구는 <> 해주고 누구는 "" 해주냐구요?ㅎ
<>를 해주는 녀석은 기본 헤더파일, "" 해주는 녀석은 우리가 직접 만들거나 외부에서 가져온 헤더파일 이라고 이해하시면 쉽겠습니다~

여튼 메인 안에 작성해 봅시다요~
(꼭 autoreleasepool 안에 작성하지 않으셔도 됩니당..ㅋㅋ)

뭐 여튼 그럼 이제 코드를 한 번 뜯어봅시다~
일단 코멘트를 보고 한 번 이해해 보려 노력해보세요~

메소드를 호출하는 방법입니다.
[클래스 또는 인스턴스의 이름 (띄어쓰기) 메소드 이름]

이런식이죠
[MyFirstClass itIsClassMethod]
아까 말씀드렸듯이, 우리는 아무런 인스턴스 생성도 하지 않았지만 클래스 메소드를 호출했습니다.

그 아래에는 인스턴스를 선언하고 초기화 합니다.
MyFirstClass *instance ;
'instance라는 이름을 가진 MyFirstClass 클래스의 인스턴스를 만들어라' 라는 의미입니다.
거기에 [[MyFirstClass alloc] init] 이라고 있는데, 이 alloc과 init이 대표적인 클래스 메소드가 되겠습니다...ㅎㅎ
이 의미는 MyFirstClass를 메모리에 할당하고 초기화하여 인스턴스를 생성한다.. 뭐 이런 의미입니다!
깊이들어가면 한도끝도 없어서... 뭐 이런 의미^^

그렇다면 MyFirstClass *instance = [[MyFirstClass alloc] init]; 이라는 녀석은 instance라는 인스턴스에 MyFirstClass라는 클래스를 초기화하여 집어넣어 주어라. 정도의 의미가 되겠습니다~

여튼 이렇게 우여곡절 끝에 인스턴스가 생성되었습니다.

그럼 이제 이 인스턴스(객체)안에 특징(내용물) 즉, 인스턴스 변수들을 세팅해 줘 봅시다.

myName이라는 인스턴스 변수에는 yagom이라고 넣어 주었습니다. 

그리고 NSString클래스의 인스턴스 변수 name이라는 녀석에다가 instance 인스턴스의 myName이라는 인스턴스 변수의 내용을 불러와서 집어넣어 줍니다.

그런데 여기서 잠깐!! 우리는 myName이라는 녀석의 getter와 setter를 만들어주지 않았는데요???
그렇죠!?
바로 @property와 @synthesize 녀석들이 자동으로 만들어 주었기 때문입니다~!

아래에 몇줄도 다 같은 내용들입니다~
주석을 잘 읽어 보시구요..^^
혹여나 이해가 안가는 부분은 댓글 주세요 ㅎㅎ

자, 그럼 대망의 결과를 확인해 볼까요?ㅎㅎㅎ


이런식으로 로그들이 찍히네요~!

정말 자세히 쓰면 한도끝도 없고, 간단히 쓰려니 간단히 쓰는것도 어렵네요..^^
지루하고 힘드셨을텐데 여기까지 읽어주셔서 감사합니다!!
여기까지 읽으신 분이 계실지도 의문이네요^^
혹여나 읽으셨다면 힘내라고 댓글 하나만 ...!! 넙죽넙죽...

정말 오래걸렸네요^^
다음에 또 알찬 내용으로 다시 올게요~
부족한 부분은 댓글 꼭 주시구요~!

뿅~!

by yagom

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

RSS Feed 받기   


↓↓↓저 열심히 썼는데 추천 한방 꾹 눌러주고 가시는 건 어떨까요? ^~^ 사랑합니다~ ↓↓↓
저작자 표시 비영리 변경 금지
신고
Posted by yagom

오늘의 주제

1. Class? Object? 


다섯 번째 시간입니다.^^

이제까지는 정말 Objective C를 배웠다고 하지도 못할 정도로 아주 기초적인 내용을 다루어 보았습니다.
지난 번에는 실수 표현방법에 대해 알아보았습니다.
조금 도움이 되셨는지요??
나중에 언젠가는 꼭 필요한 날이 올테니 알아두시길~!^^ 
지금부터 몇 번에 걸쳐 포스팅할 내용들(클래스, 메소드, 인스턴스 등등)의 내용만 이해를 하신다면,
"나 Objective C 70%는 이해했어" 라고 말하실 수 있을거예요.
정말 중요한 것이니 몇 번을 보고, 다른 싸이트를 검색하고, 직접 계속 생각하며 익히도록 하세요~!
iOS Dev 포스팅의 클래스와 객체 챕터를 인용하여 조금 더 설명을 추가하여 보았습니다.

힘겨운 발걸음을 한 번 떼어 볼까요?
스따뚜~~~~~~~~~~~~

Objective-C는 '객체지향언어'입니다.

객체지향언어는 객체지향 프로그래밍을 지향하는데요...

아.. 처음 보는 분들은 도무지 무슨말인지, 뭔소린지 도통 모르시겠죠?ㅎㅎ

사실, 모든 것을 시작을 할 때 기초를 탄탄히 다지고 하는것도 좋지만 전 지금 여러분들이 프로그래밍에 대한 지식이 전무하다고 생각을 하고 진행해 볼 생각입니다.

일단, 머리아프게 생각하지 맙시다..ㅎㅎ

지금 기초부터 정말 탄탄히 다지고 싶은분들은..

객체지향언어, 객체지향 프로그래밍, Objective-C, 객체, 인스턴스, 메소드, 클래스에 대해서 역사부터 차근차근 공부하고 오시길 바랍니다. 그러면 조금 더 이해가 잘 갈 수도 있어요^^

하.지.만...

공부하고 되돌아 오시는 분들은 그렇게 많지 않을 것 같네요.ㅎㅎ

하다가 분명히 지칠 것 같아요^^..

그냥 간단간단하게 알아두고 차근차근 한 번 생각하며 나가 봅시다~

일단 저만 믿고 와보시라니까요^^~


# Object와 Class란?

클래스. 우리나라 말로 바꿔보면, 등급? 교실? 종류? 도대체 뭘까요? 흠... 그냥 클래스입니다. 뭐 어떻게 표현할 방법이 없네요 ㅋㅋㅋ
굳이 하나 정하자면 종류??? 
Object란..? 
한글로 하면 객체입니다.

그렇다면 객체란 무엇일까요??
우리는 객체를 '내 차(My Car)'라고 생각해 봅시다.
여기석 클래스라는 녀석도 등장을 하는데, 클래스는 공장의 '생산라인'이라고 생각합시다.
공장의 생산라인에서는 똑같이 생긴 차량을 우리가 필요한 만큼 만들어 냅니다. 
이것이 클래스와 객체간의 관계입니다.

 



그림에서 보는 것과 같이..(발로그려서 죄송...ㅋㅋ) 생산라인에서 똑같이 생긴 자동차를 뽑아냅니다.
하지만 차량마다 번호가 다르고 탑승하는 사람도 제각각입니다.
이처럼 클래스는 어떠한 객체가 가지는 특정 모양에 대한 내용을 담고 있습니다.
그리고 객체는 찍혀나온 녀석이고, 우리는 그 안에 객체마다 클래스 형식에 맞춰 내가 원하는 내용들을 채워 넣을 수 있습니다. 
 

다른 방법으로 표현하면 클래스는 붕어빵을 찍어내는 쇠로된 틀이고,
오브젝트는 그 틀에서 찍혀나오는 붕어빵으로도 비유할 수 있겠습니다.
또한, 붕어빵에 넣어주는 앙금에 따라 팥앙금을 가지는 붕어빵이 될 수도, 피자맛 붕어빵이 될 수도 있죠.
겉모양은 같은데 말예요^^


또 다른 방법으로 설명해보면...
사람을 하나의 클래스로 본다면, 
우리 하나하나는 객체인 것입니다.
그리고 우리는 한 명 한 명 다른 이름을 가지고 있고, 피부색도 다르고, 성격도 다르고, 직업도 다르지요?
전부 사람이라는 같은 틀 안에서 우리는 각각 개성을 가지는 객체가 되는 것이지요^^

강아지도 강아지라는 클래스에서 나오는 객체이지만
종에따라서 색도 크기도 성격도 가지가지 입니다.
 
이제 프로그래밍에서 우리는 창조주가 되는 거에요.
사람의 틀을 가지는 클래스를 만들 수 있고, 
그 틀에는 인종, 성격, 생각 등 다양한 내용을 채울 수 있는 공간을 만들어 두는거죠.

그 후에 우리는 우리가 창조해 놓은 틀(클래스)를 이용해서 사람을 하나하나 찍어내어 만듭니다.
사람 하나를 만들어 놓고,
이름이라는 특징에는 야곰 이라고 채워 넣고
인종이라는 특징에는 황인종을 채워 넣고
외모라는 특징에는 잘생기고, 키크고...
성격이라는 특징에는 사랑스럽고 멋지고 센스있고 착하고 젠틀하다 라는 내용을 채워넣곸ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
생각이라는 특징에는 프로그래밍, 프로그래밍, 프로그래밍... 뭐 이딴것들을 채워 넣습니다.
이렇게 해서 야곰이라는 이름을 가진 객체가 탄생하는 것입니다.
하지만 이 틀(클래스)는 영원불변 하므로 언제든지 이 틀을 사용하여 또다른 사람을 만들어 낼 수 있는 것입니다.
이렇게 따지면 장동건, 원빈, 이승기... 뭐 다들 저랑 같은 틀에서 나온 사람이라 이거죠^^ㅋㅋㅋㅋㅋㅋㅋ
 

조금 이해가 가시나요? 이해가 지금 당장 가지 않으셔도 좋습니다~!
그냥 읽어두세요!!
걱정하실 필요 없구요~ 서서히 시간이 지나고 가끔씩 제가 클래스니 변수니 이런말을 무의식중에 할 때 마다 한 번씩 와서 다시 봐주세요^^ 이해가 잘 안가시면 구글에서 검색해 보시면 도움이 되는 자료들이 많을 거예요~
 
그리고 인스턴스(Instance) 또는 인스턴스변수라는 이름도 종종 보게 되실텐데요, 이녀석은 다름이 아니라 객체를 지칭하는 말입니다. 인스턴스 = 객체라고 생각하시면 됩니다.
 
그럼 여기서 대충 클래스, 객체(인스턴스)의 관계에 대하여 알아보았습니다. 책에서 보면 원론적인 내용들이 굉장히 많아서 헷갈리는 경우도 많고, 요거만 보다가 지쳐 쓰러지는 경우도 있으니.. 일단 여기서 잠시 접어둡시다~ 사실 이게 다예요^^;

정 더 궁금하시다면... 대충 흝어보고 오세요~
http://ko.wikipedia.org/wiki/%EA%B0%9D%EC%B2%B4_%EC%A7%80%ED%96%A5_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D
http://ko.wikipedia.org/wiki/%EC%98%A4%EB%B8%8C%EC%A0%9D%ED%8B%B0%EB%B8%8C-C
http://www.webdoor.org/xe/135
http://kldp.org/node/108983
별 내용은 없을거예요~

객체지향언어는 왜 사용하는지, Objective-C는 왜 C랑 다른지... 등등은 C를 배우지 않으신 분들이 아니라면 굳이 여기서 설명해 드릴 필요는 없을 것 같아요^^
다음 번 정도에 객체지향언어의 특징과 왜 객체를 사용하는지 정도에 대해서 간략히 설명해 드릴게요. (만약 제가 깜빡하고 안하면 댓글 남겨주세요..ㅎㅎ)

by yagom

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

RSS Feed 받기   


↓↓↓저 열심히 썼는데 추천 한방 꾹 눌러주고 가시는 건 어떨까요? ^~^ 사랑합니다~ ↓↓↓
저작자 표시 비영리 변경 금지
신고
Posted by yagom


티스토리 툴바