이따금 단순히 정적 메서드와 정적 필드만을 담은 클래스를 만들고 싶을 때가 있을 것이다. 전역적으로 사용하기 위해서 사용합니다. 클래스를 인스턴스화 하지 않고도 직접 호출할 수 있습니다. 보통 안티패턴이라고 이야기하는데, 그럼 언제 사용해야 할까요?
여기서도 예제를 들어주고 있는데
- 관련된 메서드들을 한데 모아놓고 사용할때 ex) java.lang.Math, java.util.Arrays (실제로 정적프로퍼티와 정적 메소드로 이루어져 있습니다.) Swift에서 기본 제공하는 Class에서는 찾을 수가 없었고 예시를 가져와봤습니다.
enum AppStyles {
enum Colors {
static let mainColor = UIColor(red: 1, green: 0.2, blue: 0.2, alpha: 1)
static let darkAccent = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 1)
}
enum FontSizes {
static let small: CGFloat = 12
static let medium: CGFloat = 14
static let large: CGFloat = 18
static let xlarge: CGFloat = 21
}
}
색상이나 글꼴 크기를 인스턴스화 시켜 앱 곳곳에 흩어져있게 하는것 보다 위와같이 한곳에 정의하는 것이 훨씬 관리하기 편합니다.
enum을 사용한 이유는 이니셜라이저가 없어 인스턴스화가 불가능하고, static property를 사용해 인스턴스화 하지 않고 바로 접근할 수 있기 때문입니다.
(전역적으로 설정 + 애초에 enum은 stored property를 가지고 있지 못합니다.)
- 특정 인터페이스를 구현하는 객체를 생성해주는 정적 메서드나 팩토리를 구현할때 ex) java.util.Collections 사용자 대신해서 객체의 인스턴스를 만들어 낸다던가, 간단하게 사용해서 복잡한 객체를 만들어 낼때 사용합니다.
enum BlogpostFactory {
static func create(withTitle title: String, body: String) -> Blogpost {
let metadata = Metadata(/* metadata properties */)
return Blogpost(title: title, body: body, createdAt: Date(), metadata: metadata)
}
}
- final 클래스와 관련한 메서드들을 모아놓을때
매개변수를 받지 않는 public 생성자가 만들어지고, 사용자는 구분할 수 없습니다.
직접 선언한 생성자가 없는 경우에 한해서 컴파일러가 자동으로 기본 생성자를 만들어준다고 합니다.
-> 해당부분은 Swift와 동일합니다.
Swift는 추상 클래스라는 것이 존재하지 않습니다.
비슷한 개념이 있다면 Protocol을 들 수 있겠습니다.
Protocol과 비슷합니다.
(재)사용할 프로퍼티와 메소드 이름을 통일하여 객체의 유지보수성을 높이고 통일성을 유지할 수 있는 장점을 얻기 위해 사용합니다.
다른 클래스가 추상 클래스를 '상속'받아 실제 내용(프로퍼티, 메소드)를 구현합니다.
Protocol은 클래스가 '채택'하여 사용이 가능합니다.
추상 클래스 관련이야기라 Swift와 관계 없다고 판단하였습니다.
(Protocol로는 인스턴스화를 막을 수 없다..와 같은 맥락은 아닌것 같다고 생각합니다.)
java에서 컴파일러가 기본 생성자를 만드는 경우는 오직 명시된 생성자가 없을때 뿐이라고 합니다.
-> Swift또한 private한 생성자를 만들 수 있습니다.
-> 여기서도 언급을 하지만, 생성자가 존재하는데 호출할 수 없는 코드는 직관적이지 않아 주석을 달아주는 것을 권장하고 있습니다.
해당 방식은 상속을 불가능하게 하는 효과가 있습니다.
: 하위 클래스를 만들더라도, 상위 클래스의 생성자에 접근하지 못하므로 상속이 이루어지지 않는 효과도 동시에 누립니다.
-> 인스턴스화 + 상속의 문제를 동시에 해결하려면 Enum을 써야하는게 맞는것 같다고 생각합니다.
-> 상속의 문제는 final class를 만들어 해결하고, 파편화된 인스턴스화가 신경이 쓰인다면 공유인스턴스 혹은 싱글톤을 만들어 사용하는게 좋은 방법이라 생각됩니다.
// 코드 4-1 인스턴스를 만들 수 없는 유틸리티 클래스 (26~27쪽)
class UtilityClass {
// 기본 생성자가 만들어지는 것을 막는다(인스턴스화 방지용).
private init() {
print("private init!")
}
// 나머지 코드는 생략
}
참고한 페이지