안녕하세요 우아한테크코스 6기에 지원하면서 코틀린을 처음 배우고 미션을 구현하면서 코드 컨벤션을 자주 보고 수정하게 되네요.
코딩을 하면서 지켜야될 규칙들이 이렇게 많구나 깨달으면서 한편으로는 우아한테크코스 덕분에 규칙이 존재한다는 걸 알게 된 것 같아요!!
코틀린 코딩에 있어 지켜야 할 규칙을 모르셨던 분들, 알고 계시지만 한번 더 보시는 분들께 도움이 되는 글이었으면 좋겠습니다.
Coding conventions | Kotlin
kotlinlang.org
코틀린 코딩 컨벤션은 위에 링크를 들어가시면 더 자세히 볼 수 있습니다.
디렉토리 구조
순수 Kotlin 프로젝트에서 권장되는 디렉터리 구조는 공통 루트 패키지가 생략된 패키지 구조를 따릅니다. 예를 들어 프로젝트의 모든 코드가 패키지 org.example.kotlin와 해당 하위 패키지에 있는 경우 패키지가 포함된 파일은 org.example.kotlin소스 루트 바로 아래에 배치되어야 하며, 의 파일은 소스 루트의 하위 디렉터리 org.example.kotlin.network.socket에 있어야 합니다. network/socket
추가 설명
위의 디렉토리는 제가 지금 사용하고 있는 디렉터리를 예시로 들었습니다.
- kotlin-baseball-6/: 프로젝트 루트 디렉토리입니다.
- src/: 소스 코드와 리소스 파일이 있는 디렉터리입니다.
- src/main/: 메인 소스 코드 및 리소스 파일을 포함하는 디렉터리입니다.
- src/main/kotlin/: Kotlin 소스 코드 파일이 있는 디렉터리입니다. Kotlin 코드 파일은 이 디렉터리에 위치합니다.
- baseball/: 패키지 구조입니다. 패키지 이름은 일반적으로 역순 도메인 이름을 포함합니다.
- Application.kt: Kotlin 소스 코드 파일입니다. 이 파일에는 Kotlin 클래스 및 함수가 정의됩니다.
- build.gradle 또는 build.gradle.kts: 프로젝트 빌드 및 의존성 설정을 관리하는 Gradle 빌드 스크립트입니다.
- settings.gradle (선택 사항): Gradle 멀티 프로젝트 세팅을 정의하는 파일입니다.
- README.md: 프로젝트에 대한 설명 및 문서를 포함하는 Markdown 파일입니다.
소스 파일 이름
Kotlin 파일에 단일 클래스 또는 인터페이스(잠재적으로 관련된 최상위 선언 포함)가 포함된 경우 해당 이름은 클래스 이름과 동일해야 하며 확장명이 추가되어야 합니다. kt. 이는 모든 유형의 클래스와 인터페이스에 적용됩니다. 파일에 여러 클래스가 포함되어 있거나 최상위 수준 선언만 포함되어 있는 경우 파일에 포함된 내용을 설명하는 이름을 선택하고 이에 따라 파일 이름을 지정하세요. 첫 글자가 대문자인 카멜 표기법 (파스칼 표기법이라고도 함)을 사용합니다 (예: ) ProcessDeclarations.kt.
소스 파일 구성
동일한 Kotlin 소스 파일에 여러 선언(클래스, 최상위 함수 또는 속성)을 배치하는 것은 이러한 선언이 의미상 서로 밀접하게 관련되어 있고 파일 크기가 합리적으로 유지되는 한(수백 줄을 초과하지 않음) 권장됩니다.
특히, 이 클래스의 모든 클라이언트와 관련된 클래스에 대한 확장 기능을 정의하는 경우 해당 클래스 자체와 동일한 파일에 배치하십시오. 특정 클라이언트에만 적합한 확장 기능을 정의하는 경우 해당 클라이언트의 코드 옆에 배치하세요. 일부 클래스의 모든 확장자를 보유하기 위해 파일을 생성하지 마십시오.
클래스 레이아웃
클래스 내용은 다음 순서로 진행되어야 합니다.
1. 속성 선언 및 초기화 블록
2. 보조 생성자
3. 메서드 선언
4. 동반 객체
추가 설명
1. 기본 생성자 (Primary Constructor)
- 클래스 정의의 일부로 선언됩니다.
- 주로 클래스의 속성(멤버 변수)을 정의하고 초기화하는 역할을 합니다.
- 주요 생성자의 파라미터는 클래스의 속성을 선언하는 것과 동시에 초기화하는 데 사용됩니다.
예시로 같이 기본 생성자를 사용한 코틀린 클래스입니다.
이 클래스는 'name'과 'age'라는 속성을 선언하며, 주요 생성자를 통해 초기화시킵니다.
class Person(val name: String, val age: Int){
// 클래스의 속성과 초기화 로직을 포함
}
2. 보조 생성자(Secondary Constructor)
- 기본 생성자 외에 클래스에 추가적인 생성자를 정의할 수 있습니다.
- 보조 생성자는 주로 다양한 초기화 시나리오를 지원하거나 기본 생성자와 다르게 동작하는 객체 생성을 제공하는 데 사용됩니다.
- 보조 생성자는 constructor 키워드를 사용하여 정의하며, 주요 생성자와의 연결을 위해 this 키워드를 사용할 수 있습니다.
class Person(val name: String, val age: Int){
// 주요 생성자
constructor(name: String) : this(name,0){
// 보조 생성자에서 주요 생성자를 호출하여 초기화
}
}
이 클래스는 name과 age를 가진 주요 생성자와 name만을 인수로 받는 보조 생성자를 제공합니다. 보조 생성자는 this(name, 0)를 통해 주요 생성자를 호출하여 초기화합니다.
코틀린의 생성자는 객체 초기화와 관련된 중요한 역할을 수행하며, 클래스의 속성을 설정하고 초기화하는 데 필수적인 부분입니다.
3. 메서드 선언
코틀린에서 메서드를 선언하는 일반적인 구문은 아래와 같습니다.
fun methodName(parameters): RetrunType {
// 메소드 본문(메소드가 수행할 동작)
return retrunValue // 선택적인 반환 값
}
- fun : 함수를 선언할 때 사용하는 키워드
- methodName : 메서드의 이름. 식별자 규칙을 따라야 하며, 관례적으로 카멜 표기법을 사용합니다
- parameters : 메서드가 받는 매개변수(parameter) 목록. 필요에 따라 매개변수를 선언하며, 매개변수는 이름과 자료형을 가집니다
- ReturnType : 메서드가 반환하는 값의 자료형을 지정합니다. 반환 값이 없는 경우 Unit 자료형을 사용하거나 생략할 수 있습니다
- 메소드 본문 : 중괄호 {} 내에 작성된 코드로, 메소드가 수행할 동작을 정의합니다
코드 예시)
class MyClass(val parameter: Int) {
// 주요 생성자와 클래스 본문
}
4. 동반객체
코틀린(Kotlin)에서 동반 객체(Companion Object)는 클래스 내부에 정적(static) 멤버 변수 및 메서드를 가지는 특별한 객체입니다.
동반 객체는 클래스 인스턴스를 생성하지 않고도 해당 클래스와 연관된 작업을 수행하는 데 사용됩니다. 이를 통해 Java의 정적(static) 멤버와 유사한 기능을 제공하며, Kotlin에서는 객체 지향 프로그래밍과 함수형 프로그래밍을 혼합하여 사용자에게 강력한 표현력을 제공합니다.
동반 객체의 주요 특징 및 사용법은 다음과 같습니다
- 클래스 내에 하나의 동반 객체만 선언할 수 있습니다.
- 동반 객체의 멤버 변수 및 메서드는 해당 클래스의 인스턴스 없이 호출될 수 있습니다.
- 동반 객체의 이름을 명시적으로 지정하거나, 생략하여 기본 이름 "Companion"을 사용할 수 있습니다.
- 동반 객체는 클래스 내에서 정의된 다른 멤버와 마찬가지로 클래스 내부 또는 클래스 외부에서 접근할 수 있습니다.
아래 코드에서 MyClass 클래스의 동반 객체를 사용하면 클래스 인스턴스를 생성하지 않고도 property1과 method1에 접근할 수 있습니다.
동반 객체는 주로 팩토리 메서드(factory method)를 제공하거나 클래스와 관련된 유틸리티 메서드를 구현하는 데 유용하며, 특히 코틀린에서는 정적 멤버를 대체하는 데 사용됩니다.
class MyClass {
companion object {
// 동반 객체의 멤버 변수
val property1 = "This is a property"
// 동반 객체의 메소드
fun method1() {
println("This is a method in the companion object")
}
}
}
fun main() {
// 클래스 인스턴스 생성 없이 동반 객체의 멤버에 접근
println(MyClass.property1)
// 동반 객체의 메소드 호출
MyClass.method1()
}
인터페이스 구현 레이아웃
인터페이스를 구현할 때 구현 멤버를 인터페이스 멤버와 동일한 순서로 유지합니다(필요한 경우 구현에 사용되는 추가 전용 메서드와 함께 배치).
추가 설명
1. 인터페이스에서 정의한 메서드의 순서와 클래스에서 해당 메서드를 구현한 순서는 동일해야 합니다. 이렇게 하면 코드를 읽는 사람이 쉽게 해당 메소드의 구현을 찾을 수 있습니다.
2. 필요한 경우 인터페이스에서 정의한 메소드의 구현 바로 다음에, 해당 인터페이스의 멤버와는 무관한 추가적인 메서드를 배치할 수 있습니다. 이 추가 메소드는 해당 인터페이스에 정의되지 않은 것이며, 클래스에서만 사용되는 메소드일 수 있습니다.
코틀린 코드 컨벤션을 따르는 클래스와 인터페이스 구현의 예시)
interface MyInterface {
fun methodA()
fun methodB()
}
class MyClass : MyInterface {
// MyInterface에서 정의한 메소드와 동일한 순서로 구현합니다.
override fun methodA() {
// 구현 내용
}
override fun methodB() {
// 구현 내용
}
// 인터페이스 메소드의 구현 다음에, 추가 메소드를 배치할 수 있습니다.
fun additionalMethod() {
// 구현 내용
}
}
이 규칙을 따르면 코드를 읽는 사람이 클래스에서 구현한 인터페이스 메서드를 쉽게 식별할 수 있고, 클래스별로 고유한 추가 메소드도 추가할 수 있습니다. 이것은 코드의 일관성과 가독성을 높이는 데 도움이 됩니다.
오버로드 레이아웃
항상 클래스에서 오버로드를 서로 옆에 배치하세요.
추가 설명
오버로딩 규칙
- 메소드 이름이 동일해야 합니다.
- 매개변수의 개수, 순서, 또는 자료형이 달라야 합니다.
- 반환 값의 자료형은 오버로딩과 관련이 없습니다.
오버로딩 예제 )
class Calculator {
fun add(a: Int, b: Int): Int {
return a + b
}
fun add(a: Double, b: Double): Double {
return a + b
}
fun add(a: String, b: String): String {
return a + b
}
}
위의 Calculator 클래스에서 add 메서드는 서로 다른 자료형의 매개변수를 사용하며, 각각 Int, Double, 그리고 String 타입에 대한 오버로딩을 제공합니다.
오버로딩된 메서드를 호출할 때, 적절한 매개변수 타입을 제공하여 호출할 메소드를 선택할 수 있습니다.
코틀린 컴파일러는 호출 시 인자에 따라 적절한 오버로딩된 메소드를 선택합니다.
예시)
val calc = Calculator()
val result1 = calc.add(5, 3) // Int 버전의 add 메소드 호출
val result2 = calc.add(3.5, 2.7) // Double 버전의 add 메소드 호출
val result3 = calc.add("Hello, ", "World") // String 버전의 add 메소드 호출
주의사항
매개변수 타입과 개수만을 기반으로 메소드를 구분하기 때문에 매개변수 이름은 오버로딩에 영향을 미치지 않습니다.
매개변수의 기본값(default values)을 사용할 때 주의해야 합니다. 동일한 매개변수 목록에 기본값이 있는 메서드와 없는 메서드는 충돌하므로 주의해야 합니다.
'Android' 카테고리의 다른 글
[ Kotiln Code conventions ] 서식 지정(Formatting) 2 (2) | 2023.10.30 |
---|---|
[ Kotiln Code conventions ] 서식 지정(Formatting) 1 (2) | 2023.10.30 |
[ Kotlin Code conventions ] 명명규칙(Naming rules) (2) | 2023.10.29 |
Kotlin 함수와 변수 (1) | 2023.10.19 |
코틀린(Kotlin) 이란? (1) | 2023.10.18 |