유튜브 강의와 책, 공식문서를 보면서 공부한 내용을 나만의 방식으로 정리하였다
https://kotlinlang.org/docs/tutorials/
코틀린 강의 추천
https://www.youtube.com/playlist?list=PLQdnHjXZyYadiw5aV3p6DwUdXV2bZuhlN
Kotlin -> JetBrains에서 만듬
JAVA의 약점을 개선 Javascript 와 Swift의 연동
추세는 Java 에서 Kotlin 으로 Migration 하는 특성을 보여줌
1. 변수와 자료형
- 그것은 진짜일까
1.1 주석
comment
//
/* */
1.2 세미콜론 안붙여도 된다
1.3 변수선언 var 과 val 이 있음
var 변경가능
val 선언시 초기화 가능, 중간에 변경 불가
1.4 기본자료형
정수 : bye, short, int, long
실수 : float, double
Boolean -> true 인지 false인지
2. 형변환, 배열
2.1 앞에 to를 붙여 명시적 형변환이 가능함
toByte()
toLong()
2.2 배열
Array<T>
var intArr = array(1, 2, 3, 4)
특정한 크기의 비어있는 배열을 만든다
var nullArr = arrayOfNulls<Int>(3)
< > 안에는 배열에 할당할 자료형을 지정해주면됨
이를 제너릭(Generic)이라고 한다
3 타입추론과 함수
반드시 특정한 자료형을 지정해야하는 상황이 아니면
그냥 할당해주면 코틀린을 알아서 자료형이 무엇인지 추정한다
4 조건문, 비교연산자
if 문의 쓰임은 기본적으로 JAVA와 동일
자료형이 맞는지 채크하는 is 연산자
틀린지를 체크하는 !is 연산자
a is Int
다중 조건문 when
when은 하나의 변수를 여러개의 값과 비교 가능
switch case의 느낌
fun useWhen(a: Any){
when(a) {
1 -> printlin("XXX")
"coding" -> printlin("man")
is Int -> println("Int 타입이다")
else -> println("어떤 조건에도 만족 X")
}
}
5 흐름제어와 논리연산자
fun main() {
loop@for(i in 1..10){
for(j in 1..10){
if(i==1 && j==2) break@loop
println("i : &i, j : &j")
}
}
}
// 코틀린에서는 외부 반복문에 레이블 이름과 @기호를 달고
// break 문에서 @과 레이블 이름을 달면 레이블이 달린 반복문을 기준으로 즉시
// break가 처리된다
6. 코틀린의 기본, 객체지향
클래스는 '값'과 그 값을 사용하는 '기능'들을 묶어 놓은것
클래스 = 고유의 특징값(속성) + 기능의 구현(함수)로 이루어져 있다.
클래스는 '인스턴스'를 만드는 틀이며 인스턴스란 클래스를 이용해서 만들어내는
서로 다른 속성의 객체를 지칭하는 용어이다
설계도를 바탕으로 소프트웨어 세계에 구현된 구체적인 실체이며 객체를 소프트웨어에 실체화 하면 그것을 ‘인스턴스’라고 부른다.
실체화된 인스턴스는 메모리에 할당된다
oop의 관점에서 객체가 메모리에 할당되어 실제 사용될 때 ‘인스턴스’라고 부른다.
인스턴스는 어떤 원본(추상적인 개념)으로부터 생성된 복제본을 말하며
Java를 기준으로 한다면
/* 클래스 */
public class Animal {
...
}
/* 객체와 인스턴스 */
public class Main {
public static void main(String[] args) {
Animal cat, dog; // '객체'
// 인스턴스화
cat = new Animal(); // cat은 Animal 클래스의 '인스턴스'(객체를 메모리에 할당)
dog = new Animal(); // dog은 Animal 클래스의 '인스턴스'(객체를 메모리에 할당)
}
}
** 참고 **
객체(Object) VS 인스턴스(Instance)
클래스의 타입으로 선언되었을 때 객체라고 부르고, 그 객체가 메모리에 할당되어 실제 사용될 때 인스턴스라고 부른다.
객체는 현실 세계에 가깝고, 인스턴스는 소프트웨어 세계에 가깝다.
객체는 ‘실체’, 인스턴스는 ‘관계’에 초점을 맞춘다.
객체를 ‘클래스의 인스턴스’라고도 부른다.
‘방금 인스턴스화하여 레퍼런스를 할당한’ 객체를 인스턴스라고 말하지만, 이는 원본(추상적인 개념)으로부터 생성되었다는 것에 의미를 부여하는 것일 뿐 엄격하게 객체와 인스턴스를 나누긴 어렵다.
https://gmlwjd9405.github.io/2018/09/17/class-object-instance.html
코틀린또한 마찬가지로 적용되며
객체지향 언어를 기반으로 함수형 언어의 장점을 흡수한 언어이다
7. 클래스의 생성자 (constructor)
생성자 :: 새로운 인스턴스를 만들기 위해 호출하는 특수한 함수
생성자를 호출하면 클래스의 인스턴스를 만들어 반환받을 수 있으며
1. 인스턴스의 속성을 초기화 할 수 있고
2. 인스턴스 생성시 구문을 수행하게 할 수 있다.
인스턴스 생성시 구문을 수행하는 기능은 어떻게 넣을까?
이는 init 이라는 특수한 함수를 통해 구현이 가능하다
init 함수는 parameter나 return이 없는 특수한 함수인데 생성자를 통해 인스턴스가 만들어질 때 호출되는 함수이다.
fun main(){
var a = Person("정국", 2000)
var b = Person("다효", 1992)
var c = Person("정현", 1996)
}
class Person(var name:String, val birthday: Int){
init{
println("${this.birthday}년생 ${this.name} 생성")
}
}
기본 생성자 : 클래스를 만들 때 기본으로 선언
보조 생성자 : 필요에 따라 추가적으로 선언
보조생성자는 기본생성자와 다른형태의 생성자를 제공, 인스턴스 생성시 편의를 제공하거나
추가적인 구문을 수행하는 역할을 한다.
보조생성자는 constructor라는 키워드를 사용하며
중요포인트 : 보조생성자를 만들 때, 반드시 기본생성자를 통해 속성을 초기화 해주어야 한다.
보조생성자가 기본생성자를 호출하도록 하려면 콜론(:) 을 붙인후 this라는 키워드를 사용하고
기본 생성자가 필요로 하는 parameter를 괄호안에 넣어준다.
fun main(){
// 기본생성자 사용
var a = Person("정국", 2000)
var b = Person("다효", 1992)
var c = Person("정현", 1996)
// x1 ~ x3 보조생성자 사용
var x1 = Person("농담")
var x2 = Person("도잘하십")
var x3 = Person("니다")
}
class Person(var name:String, val birthday: Int){
init{
println("${this.birthday}년생 ${this.name} 생성")
}
constructor(name:String) : this(name, 2000){
println("보조생성자 사용")
}
}
요약
1. 기본생성자와 보조생성자는 클래스를 사용하는 사람에게
2. 다양한 방법으로 인스턴스를 생성하는 법을 제시함
3. 사용하는 사람들에게 편의를 제공함
8. 상속
코틀린에서 상속 금지가 기본값이며
'open' 키워드를 통해 클래스가 상속될 수 있도록 클래스 선언시 붙여준다.
1. 서브클래스는 수퍼클래스에 존재하는 속성과 같은이름의 속성을 가질 수 없다
2. 서브클래스가 생성될 때는 반드시 수퍼클래스의 생성자까지 생성해야한다.
fun main(){
var a = Animal("한국", 5, "강아지")
var b = Dog("한국", 5)
a.intro()
b.intro()
}
open class Animal(var name:String, var age:Int, var type:String)
{
fun intro()
{
println("난 ${type} ${name}이며, ${age}살 이다.")
}
}
class Dog(name : String, age : Int) : Animal (name, age, "강아지")
{
}
클래스의 상속은 클래스를 좀 더 구조적으로 다룰 수 있게 만들지만
너무 많이 사용하다보면 코드 읽기가 힘들어지는 경우가 발생한다.
9. 오버라딩과 추상화
상속시에는 기본적으로 서브클래스에서 수퍼클래스와 같은이름의 형태를 만들 수 없지만
수퍼클래스에서 open시 오버라이딩이 가능하다
// 만약 타이거 클래스에서 음식을 먹는다 대신 고기를 먹습니다로 출력하려면??
fun main(){
var t = Tiger()
t.eat()
}
// fun eat() 에 open 키워드가 붙으면 Tiger에서 재구현이 가능하다!!
open class Animal {
open fun eat(){
println("음식 먹자")
}
}
class Tiger : Animal(){
// 이 때 재구현할 때 붙여주는 키워드가 override 이다
override fun eat(){
println("고기 먹자")
}
}
추상화 -> 선언부만 있고 기능이 구현되지 않은 추상함수, 그리고 추상함수를 포함하는 추상클래스로 이루어져있다
추상함수는 기본적으로 이걸 사용하려면 이것들의 기능들을 구현해
fun main()
{
}
abstract class Animal()
{
//동물은 먹고
abstract fun eat()
// 마시며
abstract fun drink()
// 싼다
abstract fun ssanda()
}
추상함수는 기본적으로 '미완성 클래스' 이며
단독으로는 인스턴스를 만들 수 없다
따라서 바드시 서브클래스에서 상속을 받아서 사용!!
사용할 때는 추상클래스에서 만들어 주었던 abstract 표시가 되어있는 녀석들을 구현해주어야 한다.
fun main()
{
var pig = Pig()
pig.eat()
pig.drink()
pig.ssanda()
}
abstract class Animal()
{
//동물은 먹고
abstract fun eat()
// 마시며
abstract fun drink()
// 싼다
abstract fun ssanda()
}
class Pig : Animal(){
override fun eat()
{
println("먹먹")
}
override fun drink()
{
println("마셔마셔")
}
override fun ssanda()
{
println("뿡뿡")
}
}
추상화를 하는 또다른 방법 : 인터페이스(interface)
인터페이스는 추상함수로만 이루어져있는 '순수 추상화 기능'을 말하는 것
코틀린에서 속성, 그리고 추상함수와 일반함수 모두 가질 수 있다.
추상함수 vs 인터페이스
추상함수는 생성자를 가질 수 있지만
인터페이스는 생성자를 가질 수 없다
인터페이스에서
구현부가 있는 함수는 open함수로 간주되며
구현부가 없는 함수는 abstract 함수로 간주된다
따라서 별도의 키워드가 없어도 포함된 모든 함수를
서브늘래스에서 구현 및 재정의가 가능하다는 특성을 가지고있다.
기본적으로 Java와 마찬가지로 한번에 여러개의 인터페이스를 상속받을 수 있음으로
좀더 유연한 설계가 가능하다.
fun main()
{
var singer = Singer()
singer.sing()
singer.dance()
}
interface Twice {
fun sing()
}
interface Roketpuch{
fun dance()
{
println("춤을 춘당")
}
}
class Singer : Twice, Roketpuch
{
override fun sing()
{
println("트와이스가 노래를 부른다")
}
// 댄스 재구현
override fun dance()
{
println("로켓펀치가 댄스를 하네 ")
}
}
#요약
오버라이딩 : 이미 구현이 끝난 함수의 기능을 서브클래스에서 변경해야 할 때 사용
추상화 : 형식만 선언하고 실제 구현은 서브클래스에 일임할 때
인터페이스 : 서로다른 기능들을 여러개 물려주어야 할 때 유용한 기능
댓글