[Dart] Class ์ด ์ ๋ฆฌ (์์ / ์ฌ์ ์ / ์ถ์ํ)
Singleton Pattern
์ด๋ฒ ๊ธ์์๋ Singleton? Static? Class? ์ ์ฐจ์ด์ ์ ๋ํด์ ์์๋ณด๋๋ก ํ๊ฒ ๋ค.
๋น์ทํด ๋ณด์ด์ง๋ง ์ด ๋ค์ ์ฐจ์ด์ ์ ๋ช ํํ๊ฒ ๋ค๋ฅธ ๊ฐ๋ ๋ค์ด๊ณ , ์ ํํ๊ฒ ๊ฐ๋ ๋ค์ ์ดํดํ๊ณ ์์ด์ผ ํ๋ค.
Class, Static์ Flutter ๊ฐ๋ฐ์ ํ์ง ์์๋๋ผ๋ ์์ฃผ ์ ํ๊ณ ์ฌ์ฉํด๋ณธ ๊ฐ๋
๋ค์ด๋ค.
Singleton์ ๋ํด์๋ ๋ฏ์ ๊ฐ๋
์ผ ์๋ ์์ง๋ง ์ด๋ฏธ Flutter ๊ฐ๋ฐ์ ์ฌ์ฉํ๋ ๊ธฐ๋ฅ๋ค ์ค์ Singleton์ ๊ฐ๋
์ผ๋ก ๊ฐ๋ฐ๋ ๊ธฐ๋ฅ๋ค์ด ๋ค์์์ด ์ฌ์ฉํด ๋ณธ ์ ์ด ์์ ๊ฒ์ด๋ค.
๊ฐ๋ ๋ค์ ์ฐจ์ด์ ์์ฃผ๋ก ๋น๊ตํด ๋ณด๋ฉด์ ์์๋ณด๋๋ก ํ์.
Classes
Dart is an object-oriented language with classes and mixin-based inheritance. Every object is an instance of a class, and all classes except Null descend from Object. Mixin-based inheritance means that although every class (except for the top class, Object?) has exactly one superclass, a class body can be reused in multiple class hierarchies. Extension methods are a way to add functionality to a class without changing the class or creating a subclass. Class modifiers allow you to control how libraries can subtype a class.
๋จผ์ ์ด ๋ค์ ์ฐจ์ด์ ์ ์์๋ณด๊ธฐ์ ์์ Instance๋ผ๋ ๊ฐ๋ ์ ๋ํด์ ์๊ณ ์์ด์ผ ํ๋ค.
Instance๋ ๋ฌด์์ผ๊น ?
์ธ์คํด์ค๋ผ๋ ๋ง์ ์์ฃผ ๋ฃ๊ณ ์ฌ์ฉํด ๋ดค์ ๊ฒ์ด๋ค.
์ธ์คํด์ค๋ Class๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์์ฑ๋๋ฉฐ, Class์ ๊ธฐ๋ฅ๊ณผ ์์ฑ์ ๋์ผํ๊ฒ ๊ฐ์ง๊ณ ์๋ ํ๋ก๊ทธ๋๋ฐ ์์์ ์ฌ์ฉ๋๋ ๋์์ด๋ค.
์ค๋ช
์ด ์ ์ดํด๋์ง ์์ ์๋ ์๋ค. ์ฝ๊ฒ ๊ฐ๋
์ ์ค๋ช
ํ์๋ฉด Class๊ฐ ์์ฑ๋์ด ์ง๊ณ , ์์ฑ๋ Class๊ฐ ์ฌ์ฉ๋์ด ์ง๋ฉด์ ๋ฉ๋ชจ๋ฆฌ์ ํ ๋น ๋์์ ๋, ์ด๋ฅผ Object(๊ฐ์ฒด)๋ผ๊ณ ํ๋ค.
์ ์ ๋ฐ์ ๋ฉ๋ชจ๋ฆฌ์ ํ ๋น๋๋ ๊ณผ์ ์ ์ธ์คํด์คํ๋ผ๊ณ ์ ์ํ๋ค.
์ด์ฒ๋ผ Instance๋ผ๋ ๊ฐ๋
์ Class๊ฐ Object(๊ฐ์ฒด)๋ก ์ ์ธ๋๊ณ , ์ ์ธ๋์ด์ง Object(๊ฐ์ฒด)๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ํ ๋น ๋์ด ์ค์ ์ฌ์ฉ๋ ๋๊ฐ ๋ฐ๋ก Instance(์ธ์คํด์ค)์ด๋ค.
์ฆ, Object(๊ฐ์ฒด)๋ฅผ ์ค์ฒดํํ ๊ฐ๋
์ด๋ค
Class๋ฅผ ์์ฑํด ๋ณด๋๋ก ํ์.
๋ฌธ์์ด์ name, ์ ์ํ age ๋ณ์๋ฅผ ๋ฉค๋ฒ๋ณ์๋ก ์ถ๊ฐํ Person ๊ฐ์ฒด๋ฅผ ์์ฑํ์๋ค.
class Person {
final String name;
final int age;
const Person(this.name, this.age);
}
์ด์ Person ๊ฐ์ฒด๋ฅผ ์ ์ธํด๋ณด๋๋ก ํ์.
Constructor(์์ฑ์)๋ฅผ ํตํด Person ๊ฐ์ฒด๋ฅผ ์ธ์คํด์ค ํ์๋ค. ์ด์ ์ค์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ Person ๊ฐ์ฒด์ ์ธ์คํด์ค๊ฐ ์์ฑ๋ ๊ฒ์ด๋ค.
void main() {
Person _person = Person("tyger", 100);
}
Static์ ์ ์ . ์ฆ, ๊ณ ์ ๋์๋ค๋ ์๋ฏธ๋ค.
๊ณ ์ ๋์๋ค๋ ๊ฒ์ด ๋ฌด์จ ์๋ฏธ๋ฅผ ๋ํ๋ด๋ ๊ฑธ๊น ?
Static์ Static Method, Static Variable์ด ์๋ค.
Static์ผ๋ก ์ ์ธ๋๋ฉด ํ๋ก๊ทธ๋๋ฐ์ ์คํ๋ถํฐ ์ข ๋ฃ๊น์ง์ ๋ผ์ดํ์ฌ์ดํด ์ฃผ๊ธฐ ๋์ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๊ณ ์ ๋์๋ค๋ ๊ฒ์ด๋ค.
์ผ๋ฐ์ ์ธ Class๊ฐ ์์ฑ๋์ด์ง ๋์ ์ธ์คํด์ค ๊ณผ์ ์ ๊ฑฐ์น๋ ๊ฒ๊ณผ๋ ๋ค๋ฅด๊ฒ Static ๊ตฌ๋ฌธ์ ํ๋ก๊ทธ๋๋ฐ์ด ์คํ๋์ด ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ์ฌ๋ ค์ก์ ๋ ๋จ ํ๋ฒ๋ง ๋ณ๋์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ํ ๋น๋์ด ์ง๋ค.
์ด๋ ๊ฒ ์์ฑ๋ Static ๊ตฌ๋ฌธ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณต์ ํ๊ธฐ ๋๋ฌธ์ ์ ๋ณด ๋ํ ๊ณต์ ๋ ๋ค๋ ๊ฒ์ ๊ธฐ์ตํด์ผ ํ๋ค.
Static ๊ตฌ๋ฌธ์ GC(Garbage Collector)์ ๋์์ด ์๋๊ธฐ ๋๋ฌธ์ ๋ถํ์ํ ๊ตฌ๋ฌธ์ Static์ผ๋ก ์์ฑํ๊ฒ ๋๋ฉด ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ์ ์ ํ๊ฒ ๋์ด ํผํฌ๋จผ์ค๋ฉด์์ ์ข์ง ์์ ์ ์๊ธฐ์, ์ด ์ ์ ์ฃผ์ํด์ผ ํ๋ค.
GC(Garbage Collector)
๋ฉ๋ชจ๋ฆฌ ์์ญ์ ์์คํ ์ด ์๋์ ์ผ๋ก ํด์ ํด ์ฃผ๊ณ , ๊ฐ์ฉ์ํ๋ก ๋๋ ค์ฃผ๋ ๊ธฐ๋ฅ. ํ์ง๋ง, ์คํ ์กฐ๊ฑด์ ์ผ์ ํ์ง ์์.
๋ฌธ์์ด name ๋ณ์๋ฅผ Static Variable(์ ์ ๋ณ์)๋ก ์์ฑํ์๊ณ , name์ ์ถ๋ ฅํ๋ printName ๋ฉ์๋๋ฅผ Static Method(์ ์ ๋ฉ์๋)๋ก ์์ฑํด ์ฃผ์๋ค.
class Person {
static final String name = "tyger";
static void printName() {
print(name);
}
}
Static ๊ตฌ๋ฌธ์ผ๋ก ์์ฑ๋ ๊ฒฝ์ฐ ๋ณ๋์ ์ธ์คํด์คํ ๊ณผ์ ์์ด ์ด๋ฏธ ํ๋ก๊ทธ๋๋ฐ์ด ์คํ๋ ๋์ ๋ณ๋์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ํ ๋น๋์ด ์ก๊ธฐ ๋๋ฌธ์, ๋ฐ๋ก ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
void main() {
Person.printName();
String _name = Person.name;
}
"In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one โsingleโ instance. This is useful when exactly one object is needed to coordinate actions across the system. The term comes from the mathematical concept of a singleton."
์ด๋ฒ์ Singleton์ ๋ํด์ ์์๋ณด์.
Singleton์ ์์ํ๊ณ ์ด๋ ค์ธ ์ ์์ง๋ง ์ด๋ ค์ด ๊ฐ๋ ์ด ์๋๋ ๊ฑฑ์ ํ์ง ์์ผ์ ๋ ๋๋ค.
Flutter๋ฅผ ์ฌ์ฉํด ๊ฐ๋ฐ์ ํด๋ณธ ๊ฒฝ์ฐ, shared_preferences, firebase ๋ฑ์ ํจํค์ง๋ฅผ ์ฌ์ฉํด๋ณธ ๊ฒฝํ์ด ์์ ๊ฒ์ด๋ค.
ํด๋น ํจํค์ง๋ ๋ชจ๋ Singleton Pattern์ ๊ธฐ๋ฐ์ผ๋ก ๊ฐ๋ฐ๋์๋ค.
Singleton Pattern์ ๋จ ํ๋์ Instance๋ง ์์ฑํ๋ ๋์์ธ ํจํด ๊ธฐ๋ฒ์ด๋ค.
๋จผ์ Singleton์ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์์๋ณด๋๋ก ํ์.
Singleton์ผ๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ์ด๋ค.
_(์ธ๋๋ฐ)๋ฅผ ์ฌ์ฉํ private์ผ๋ก Constructor(์์ฑ์)๋ฅผ ๋ง๋ค์ด ์ฃผ์๋ค.
class Person {
static final Person instance = Person._internal();
factory Person() => instance;
Person._internal();
}
Singleton์ผ๋ก ์์ฑ๋ ๊ฐ์ฒด์ Instance ๋ฐฉ๋ฒ์ Static ๋ณ์๋ฅผ ์ฌ์ฉํด๋ ๋๊ณ , Class๋ฅผ ์ฌ์ฉํด ์ธ์คํด์คํ ํ ์ ์๋ค.
void main() {
Person _person1 = Person.instance;
Person _person2 = Person();
}
์ด๋ฒ์๋ Named Constructor๋ก ๋ง๋ค์ด๋ณด๋๋ก ํ์.
class Person {
static final Person instance = Person.init();
factory Person() => instance;
Person.init();
}
์ง๊ธ๊น์ง Singleton, Static, Class์ ๋ํด์ Instance ๊ด์ ์์ ๊ฐ๊ฐ์ ๊ฐ๋ ์ ๋ํด ์ดํด ๋ณด์๋ค.
Class๋ ๊ฐ์ฒด๋ฅผ ์ธ์คํด์คํ ํ ๋๋ง๋ค Instance๊ฐ ๋งค๋ฒ ์์ฑ์ด ๋๋ค๊ณ ํ๋ค. ๋ฐ๋ฉด Singleton์ ๋จ ํ๋์ Instance๋ง์ ์์ฑํ๋๋ก ๊ฐ์ ํ๋ ํจํด ๊ธฐ๋ฒ์ด๋ผ๊ณ ํ๋ค.
Static์ Class, Singleton๊ณผ๋ ๋ค๋ฅด๊ฒ ์ธ์คํด์คํ ๊ณผ์ ์ ๊ฑฐ์น์ง ์๊ณ ํ๋ก๊ทธ๋๋ฐ ์คํ์ ๋ณ๋์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ํ ๋น์ํค๋ ๋ฐฉ๋ฒ์ด๋ค.
์ฝ๋๋ฅผ ํตํด ๊ฐ๊ฐ์ ์ฐจ์ด์ ์ ๋ํด์ ์ดํด๋ณด๋๋ก ํด๋ณด์.
Person์ด๋ผ๋ ๊ฐ์ฒด๋ฅผ ์์ฑํ ๊ฒ์ธ๋ฐ, ๋ณ์๋ก๋ ๊ฐ๊ฐ name์ ๋ฃ์ด์ ์์ฑํด ์ค ๊ฒ์ด๋ค.
Class
class PersonClass {
final String name = "tyger";
}
Singleton
class PersonSingleton {
static final PersonSingleton instance = PersonSingleton._internal();
factory PersonSingleton() => instance;
PersonSingleton._internal();
final String name = "tyger";
}
์ด์ PersonClass๋ฅผ ์ฌ์ฉํด 3๊ฐ์ ์ธ์คํด์ค๋ฅผ ์์ฑํด ๋ณด๋๋ก ํ์.
void main() {
PersonClass _personClass1 = PersonClass();
PersonClass _personClass2 = PersonClass();
PersonClass _personClass3 = PersonClass();
}
์ด์ ๊ฐ์ฒด๋ฅผ ์๋ณํ ์ ์ํ ๊ณ ์ ๊ฐ์ธ hashCode๋ฅผ ์ถ๋ ฅํด ๊ฐ๊ฐ์ ์ธ์คํด์ค๊ฐ ๋์ผํ์ง ์๋์ง ํ์ธํด ๋ณด์.
hashCode ๊ฐ์ด ๊ฐ๊ฐ ๋ค๋ฅด๊ฒ ๋์ค๋ ๊ฒ์ ์ ์ ์๋ค. ์ด๊ฒ์ด ๋ปํ๋ ์๋ฏธ๋ ๊ฐ๊ฐ์ ๊ฐ์ฒด๊ฐ ์๋ก ๋ค๋ฅธ Instance๋ก ์์ฑ์ด ๋์๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค.
Person ํด๋์ค๋ 3๊ฐ์ ์ธ์คํด์คํ ๊ณผ์ ์ ๊ฑฐ์น๋ฉด์ ๊ฐ๊ฐ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ํ ๋น ๋ฐ๊ฒ ๋๋ค.
void main() {
print(_personClass1.hashCode);
print(_personClass2.hashCode);
print(_personClass3.hashCode);
// 160990205
// 519856303
// 1035798228
}
์ด๋ฒ์ ์ฑ๊ธํค์ผ๋ก ์์ฑํ PersonSingleton ํด๋์ค๋ฅผ 3๊ฐ์ ๊ฐ์ฒด๋ก ์ ์ธํด๋ณด์.
void main() {
PersonSingleton _personSingleton1 = PersonSingleton.instance;
PersonSingleton _personSingleton2 = PersonSingleton.instance;
PersonSingleton _personSingleton3 = PersonSingleton.instance;
}
์ด๋ฒ์๋ hashCode๋ฅผ ์ถ๋ ฅํด ์ธ์คํด์ค๊ฐ ํ ๊ฐ์ ์ธ์คํด์ค๋ง ์์ฑ ๋์๋์ง ํ์ธํด๋ณด์.
๋ชจ๋ ๋์ผํ hashCode ๊ฐ์ด ์ถ๋ ฅ๋์๋ค. ์ธ์คํด์ค๊ฐ ๋จ ํ๋๋ง ์์ฑ์ด ๋ ๊ฒ์ด๋ค.
void main() {
print(_personSingleton1.hashCode);
print(_personSingleton2.hashCode);
print(_personSingleton3.hashCode);
// 1050882430
// 1050882430
// 1050882430
}
Static
๋ง์ง๋ง์ผ๋ก Static ๋ณ์๋ก name์ ์์ฑํด ์ฃผ๋๋ก ํ์.
Person ํด๋์ค๋ ์ธ์คํด์ค์์๋ name์ ์ ๊ทผํ ์ ์๋๋ก ํด์ฃผ๊ธฐ ์ํด getter๋ฅผ ์ถ๊ฐํด ์ฃผ์๋ค.
changed() ๋ฉ์๋๋ฅผ ์ถ๊ฐํ์ฌ static ๋ณ์์ ๊ฐ์ ๋ณ๊ฒฝํด ์ค ์ ์๋๋ก ํ์๋ค.
class Person {
String get nameGetter => name;
static String name = "tyger";
void changed(String data){
name = data;
}
}
์์ฑํ Person ํด๋์ค๋ฅผ ์ธ์คํด์คํ ํ getter๋ฅผ ์ฌ์ฉํด name ๊ฐ์ ์ถ๋ ฅํด ๋ณด๋๋ก ํ์.
_person1, _person2๋ ๋์ผํ Class๋ฅผ ์ธ์คํด์ค ํ์์ง๋ง, ์ธ์คํด์ค๋ 2๊ฐ๊ฐ ์์ฑ๋ ๊ฒ์ด๋ค.
๊ฐ๊ฐ์ ์ธ์คํด์ค์ ์๋ name ๊ฐ์ ๋น์ฐํ ๋์ผํ ๊ฐ์ ์ถ๋ ฅํด ์ฃผ๊ณ ์๋ค.
void main() {
Person _person1 = Person();
Person _person2 = Person();
print(_person1.nameGetter);
print(_person2.nameGetter);
// tyger
// tyger
}
์ ์ด๋ฒ์ _person1 ์ธ์คํด์ค์์๋ง name ๊ฐ์ ๋ณ๊ฒฝํด์ฃผ๋ ํจ์๋ฅผ ํธ์ถํด ๋ณด์.
์ด๋ ๊ฒ ๋๋ฉด ์ด๋ป๊ฒ ๋ ๊น ?
_person1์ name ๋ณ์๋ง ๊ฐ์ด ๋ณ๊ฒฝ๋๋ ๊ฒ์ด ์๋ ์๋ก ๋ค๋ฅธ ์ธ์คํด์ค์ธ _person2 ์ธ์คํด์ค๋ ๊ฐ์ด ๋ณ๊ฒฝ๋ ๊ฒ์ ์ ์ ์๋ค.
Static์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณต์ ํ๊ธฐ ๋๋ฌธ์ ๋น์ฐํ ํด๋น ๋ฐ์ดํฐ๋ ๊ณต์ ํ๊ฒ ๋๋ค.
void main() {
Person _person1 = Person();
Person _person2 = Person();
_person1.changed("alice");
print(_person1.nameGetter);
print(_person2.nameGetter);
// alice
// alice
}
Class, Singleton, Static์ ์ธ์คํด์ค์ ๊ฐ๋ ๊ณผ ๊ด์ ์ผ๋ก ๋ฐ๋ผ๋ณธ ์ฐจ์ด์ ์ ๋ํด์ ์์๋ณด์๋ค.
๋ถํ์ํ ์ธ์คํด์ค๊ฐ ๋ง์ด ์์ฑ๋๋ ๊ฒ๋ ์ข์ง ์์ง๋ง, ์ฑ์ ์คํ ์ฃผ๊ธฐ ๊ณผ์ ์์ ๋ฉ๋ชจ๋ฆฌ ์ ์ ๊ฐ ๋ถํ์ํ๊ฒ ๋ฐ์ํ์ฌ ํผํฌ๋จผ์ค์ ๋ฐ๋ฅธ ์ฑ๋ฅ ์ ํ ๋ถ๋ถ๋ ๊ณ ๋ คํด์ ๊ฐ๋ฐ์ ํ๋ฉด ์ข์ ๊ฒ ๊ฐ๋ค.
ํด๋น ๋ด์ฉ์ ๋ํด ๊ถ๊ธํ์ ๋ถ๋ถ์ด๋ ์ถ๊ฐํ๋ฉด ์ข์ ๋ด์ฉ ์์ผ์๋ฉด ๋๊ธ ๋จ๊ฒจ์ฃผ์ธ์ !