Class vs Struct

Updated:

🔷 Struct

  • Struct 은 값을 복사해서 사용하기 때문에 프로젝트에서 model 에 주로 사용됩니다.

  • model 에서 사용된 struct 객체는 view 단계에서 참조해서 사용할 때, 이것이 복사되어서 자동으로 초기화 되서 각 개별적으로 사용하게 됩니다

// 데이터 model 을 담아 올을때 class 와 struct 2종류를 사용하게 됩니다
// struct: memberWise initializer 때문에 좋다
// 생성자를 만들지 않아도 좋습니다. 자동으로 생성자 생성
struct YoutuberStruct {
	var name: String
	var subscriberCount: Int
	// class 와 다르게 initializer 가 필요없음 (자동생성, object 사용시, 자동으로 메모리에 등록됨 )
}

var devJacob = YoutuberStruct(name: "Jacob", subscriberCount: 9999)

var devJacobCopy = devJacob

// 값을 볻사해서 다른 메모리를 참조하기 때문에 변수 값이 다르게 됨
// struct 은 원래 값에 영향을 미치지 않음
print("devJacobCopy.name: \(devJacobCopy.name)") // Jacob
devJacobCopy.name = "Emma"
print("devJacobClone.name: \(devJacobCopy.name)") // Emma

🔶 struct mutating

// 맴버 변수 name 를 가지는 struct
// struct 는 참조인 class 와 다르기 때문에
// struct 구조의 맴버 변수 값을 변경하려면
// mutating 키워드가 필요
// struct 는 값이고 class 는 주소를 참조하는 형태라서 struct 에서 값을 변경 할때는
// 앞에 mutating 을 붙여 줘야 하는 것임

struct Friend {
	var name : String
	// mutating 키워드로 맴머 변수의
	// 값을 변경하는 메소드
	mutating func changeName(newName: String) {
		self.name = "hello! " + newName
	}
}

// 위의 것을 class 로 표현하면
class Friend2 {
	var name : String

	func changeName2(newName: String) {
		self.name = "hello! " + newName
	}

	init(_ name: String) {
		self.name = name
	}
}

var myFriend2 = Friend2("Jacob")
myFriend2.changeName2(newName: "Emma") // 이름을 바꾸기

myFriend2.name

🔶 struct method

  • struct 에서도 class 와 마찬가지로 메소드를 가질 수 있고 () 맴버 변수들 활용이 가능합니다 (struct 안에서 함수 사용이 가능하다는 것임)
struct Friend {
	var age: Int
	var name: String

	func sayHello() -> String {
		print("sayHello()")
		return "저는 \(age) 살 입니다"
	}
}

var myFriend = Friend(age: 40, name: "Jacob")
myFriend.sayHello() // "저는 40 살 입니다"

🔶 struct 기본 생성자

// struct 는 클래스와 당리 생성자 메소드가 자동 탑제되어 있습니다
struct Developer {
	var name : String
}
let developer = Developer(name: "Jacob")
print(developer) // Developer(name: "Jacob")

// 생성자를 안에서 따르 지정 가능하지만
struct Friend {
	var name: String
	init () {
		name = "Emma"
	}
}
let myFriend = Friend()
print(myFriend) // Friend(name: "Emma")

// 아래와 같이 extension 으로 빼서 기본 생성자 지정이 가능합니다
struct Pet {
	var name: String
}
extension Pet {
	init () {
		name = "냥냥이"
	}
}
let myPet = Pet()
print(myPet) // Pet(name: "냥냥이")

let myDog = Pet(name: "멍멍이")
print(myDog) // Pet(name: "멍멍이")

🔷 class

  • class 는 struct 와 같이 데이터들의 모음 이지만, 가장큰 차이점은 복사해서 사용하더라도 같은 메모리를 참조합니다

  • 즉, 복사한 객체의 값이 변경되면 같은 메모리에 속한 원본 데이터의 값도 같이 변경되게 됩니다

// class : 직접 생성자를 만들어 줘야한다(메모리에 올려줘야 한다)
class YoutuberClass {
	var name: String
	var subscriberCount: Int

	// initializer 생성 - 메모리 올리기
	// init 으로 만든 매개변수를 가진 생성자 메소드를 만들어야 매개변수를 넣어서 그 값을 가진 객체(object)를 만들 수 있다
	init(name: String, subscriberCount: Int) {
		self.name = name
		self.subscriberCount = subscriberCount
	}
}

var devMike = YoutuberClass(name: "Mike", subscriberCount: 1000)

var devMikeClone = devMike

print("값 넣기 전 devMike.name: \(devMike.name)") // Mike
print("값 넣기 전 devMikeClone.name: \(devMikeClone.name)") // Mike

devMikeClone.name = "Smith" // 이름 값 변경
print("값 넣기 전 devMike.name: \(devMike.name)") // Smith
print("값 넣기 후 devMikeClone.name: \(devMikeClone.name)") // Smith
// Clone 값이 변하면 원본데이터도 같이 변하게 됨

🔶 class func (클래스 메소드)

// 친구 클래스
class Friend {
	// 일반적인 메소드
	func sayHi() {
		print("안녕")
	}

	// 클래스 메소드로 해당 인스턴스가 생성되지 않아도 호출 가능
	class func sayBye() {
		print("바이바이~!")
	}
}

// 일반적인 형태는 인스턴스 생성해야 해당 메소드 호출이 가능합니다
let myFried = Friend()
myFried.sayHi() // 안녕

// 인스턴스 생성을 하지 않아도
// 클래스에 바로 접근해서 메소드 호출이 가능합니다
Friend.sayBye() // 바이바이~!

🔶 Static, Final Class Method

class MyClass {
	// 클래스 메소드 인스턴스를 생성하지 않고 메소드 호출이 가능한데
	// final class 메소드와 static class 메소드도 동일합니다
	class func sayHi() -> String {
		return "안녕?!"
	}
	static func sayHello() -> String {
		return "안녕하세요?!"
	}
	final class func sayHelloFinal() -> String {
		return "호호 안녕하새요?!"
	}
}

print(MyClass.sayHi()) // 안녕
print(MyClass.sayHello()) // 안녕하세요?!
print(MyClass.sayHelloFinal()) // 호호 안녕하세요?!

// 클래스 메소드는 오버라이딩이 가능하지만
class HahaClass: MyClass {
	override class func sayHi() -> String {
		return "sayHi() HahaClass 에서"
	}
}
print(HahaClass.sayHi()) // sayHi() HahaClass 에서

// static 과 final method 들의 부모 클래스 메소드를 오버라이딩 할 수 없음
override static func sayHello() -> String {
	return "sayHello() HahaClass 에서"
} // override' can only be specified on class members

override class func sayHelloFinal() -> String {
	return "sayHelloFinal() HahaClass 에서"
} // override' can only be specified on class members


Reference

The SwiftLanguage Guide: 클래스과 구조체 (Classes and Structures)- https://jusung.gitbook.io/the-swift-language-guide/language-guide/09-classes-and-structures

개발하는 정대리 스위프트 기초 문법 - 6일차 / 클래스 vs 스트럭트 - https://www.youtube.com/watch?v=60VSuIY81iQ

Categories:

Updated:

Leave a comment