Kotlin 사이트(https://play.kotlinlang.org/)에 접속하여 별도의 설치 없이 개발할 수 있음!
Kotlin의 특징
① Java와 100% 상호 호환되므로 Java 코드를 완전히 대체 가능
② Java보다 문법이 간결함
③ 프로그램의 안정성을 높여줌
④ var 또는 val 예약어를 통해 데이터 형식을 선언하지 않고 변수를 선언할수 있음
Kotlin의 변수 선언 방식
2) var(variable) - 변수
• 일반 변수를 선언할 때 사용
• 필요할 때마다 계속 다른 값을 대입 가능
3) val(value) - 상수
• 변수 선언과 동시에 값을 대입하거나, 초기화 없이 선언한 후에 한 번만 값을 대입 가능
• 한 번 값을 대입하고 나면 값을 변경할 수 없음
Kotlin의 변수 선언 방식
암시적 선언
• 변수의 데이터 형식을 지정하지 않고, 대입되는 값에 따라 자동으로 변수의 데이터 형식이 지정
– 단, 초기화하지 않는 경우에는 데이터 형식을 반드시 명시해야 함
Kotlin에서 많이 사용되는 기본적인 데이터 형식
- 다른 언어들과 다르게 코틀린에서char타입은 2바이트 (다른 언어는 1바이트)
데이터 형변환
- .toInt()
- .toDouble()
- .to+데이터타입()
null사용
- Kotlin은 기본적으로 변수에 null 값을 넣지 못함
- 변수를 선언할 때 데이터 형식 뒤에 ?를 붙여야 null 대입 가능
- 변수가 null 값이 아니라고 표시해야 하는 경우 !!로 나타냄
- 컴퓨터에게 null이 아니라는 것을 알려줌
var notNull : Int = null //오류
var okNull : Int? = null //정상
okNull = 10
notNull = okNull //오류
//okNull에는 현재 null이 아닌 값이 들어와 있지만
//null이 들어올 수도 있는 변수이기 때문에 오류가 남
notNull = okNull!! //정상
//null이 들어올 수 없도록 !!를 적어줌
오류가 안날 수도 있는데 가급적이면 문법 맞춰주기..
when문
- 여러 가지 경우에 따라서 어떤 작업을 할 것인지를 결정
- 다중 분기라고도 부름
- switch문과 비슷 (break문이 default로 있음 - 굳이 break처리를 해주어야 할 필요가 없음)
- 범위로 처리 : in 키워드 사용
fun main() {
var count:Int = 85
when(count){
100 -> println("when문 : 합격 (장학생)")
in 90..99 -> println("when문 : 합격(장학생)")
in 60..89 -> println("when문 : 합격")
50,40,30 -> println("콤마로 or연산자처럼 처리할 수도 있음")
else -> println("when문 : 불합격")
}
}
배열
- 1차원배열은 두가지 방법으로 선언이 가능
- var one1 = Array<Int>(4,{0})
one1 = arrayOf(1,2,3,4) - var one2 = IntArray(4)
one2 = intArrayOf(1,2,3,4)
- var one1 = Array<Int>(4,{0})
fun main() {
//1차원배열
var one1 = Array<Int>(4,{0})
one1 = arrayOf(1,2,3,4)
//one[0] = 10
//one[1] = 20
println(one1[0]+one1[1]) //결과 3
var one2 = IntArray(4)
one2 = intArrayOf(1,2,3,4)
//one[0] = 10
//one[1] = 20
println(one2[0]+one2[1]) //결과 3
//2차원배열
//var two = Array<IntArray>(3,{IntArray(4)})
var two = Array<Array<Int>>(3, {Array<Int>(4,{0})})
two[0][0] = 100
two[2][3] = 200
println(two[0][0]+two[2][3]) //결과 300
//3차원배열
var three = Array<Array<Array<Int>>>(3, {Array<Array<Int>>(3, {Array<Int>(3,{0})})})
//Array<Array<Int>> : 2차원배열
//2차원부터는 배열의 선언이 깔끔하지 않기 때문에 잘 사용하지 않음
//1차원배열을 주로 사용함
}
ArrayList
- Array와 다른점 : Array는 초기에 설정된 크기 이상으로 값을 추가할 수 없지만 ArrayList는 요소를 추가할 수 있음
- 가변크기
fun main() {
var one = ArrayList<Int>(1) //초기 선언에서 크기를 1만큼만 지정
one.add(10)
one.add(20) //지정한 크기를 넘어감
var hap = one.get(0) + one.get(1)
println(hap) //정상 출력
}
for문
- i(첨자)를 사용하여 배열의 값을 하나씩 처리하는 방법
/**
* You can edit, run, and share this code.
* play.kotlinlang.org
*/
fun main() {
var two : Array<String> = arrayOf("하나", "둘", "셋")
for (i in 0..2 step 1) { //1. 인덱스 0부터 2까지 1씩 증가
print(two[i]+" ")
}
println() //한 줄 띄우기
for (i in 0..2) { //2. 1번과 같은 기능(step 1 생략가능)
print(two[i]+" ")
}
println() //한 줄 띄우기
for (i in two.indices) { //3. 배열의 크기만큼 : 배열명.indices
print(two[i]+" ")
}
println() //한 줄 띄우기
for (i in 2 downTo 0 step 1) { //4. 거꾸로 출력 : downTo (<->'..')
print(two[i]+" ")
}
}
/* 출력결과 :
하나 둘 셋
하나 둘 셋
하나 둘 셋
셋 둘 하나 */
- i(첨자) 없이 바로 배열의 값을 하나씩 처리하는 방법
fun main() {
var two:Array<String> = arrayOf("하나","둘","셋")
for(a in two){ //배열의 내용이 하나씩 변수에 대입된 후 for 문 내부 실행
println(a)
}
var k:Int = 0
while(k<one.size){
println(one[k])
k++
}
}
/* 출력결과 :
하나
둘
셋
10
20
30
10
20
30
*/
메소드와 전역변수, 지역변수
var myVar:Int = 100 //전역변수
fun main() {
var myVar:Int = 0 //지역변수
println(myVar)
var sum:Int = addFunction(10,20)
println(sum)
}
fun addFunction(num1:Int, num2:Int):Int{
var hap:Int
hap = num1+num2+myVar //전역변수인 myVar의 값을 가져옴
return hap
}
/* 출력결과 :
0
130
*/
연산자
- 대부분의 언어들에서 볼 수 있는 연산자들과 기능이 유사한 것들이 많음
- 코틀린에서의 ===연산자 : 동일한 객체인지 확인하게 해줌
- a=10, b=10일 때 a==b(O), a===b(X)
- 이런 경우, 표기법은 a==b, a!==b
fun main() {
var a = Pair('a',65)
var b = a
var c = Pair('a',65)
println(String.format("%s, %s",a == b, a == c))
println("${a===b} ${a===c}")
//${식} -> 식의 결과를 출력
}
/* 출력결과 :
true, true
true false
*/
클래스 정의와 인스턴스 생성, 생성자, 메소드 오버로딩
- Car 클래스를 구현
- 오버로딩 : 한 클래스 내에서 메소드의 이름이 같아도 파라미터의 개수나 데이터 형식만 다르면 여러 개를 선언할 수 있음
class Car{
var color:String = ""
var speed:Int = 0
constructor(){} //default생성자
constructor(color:String, speed:Int){ //생성자 추가 (오버로딩)
this.color = color
this.speed = speed
}
fun upSpeed(value:Int){
if(speed+value >= 200)
speed = 200
else
speed = speed + value
}
fun downSpeed(value:Int){
if(speed-value <= 0)
speed = 0
else
speed = speed - value
}
}
- 정의한 Car 클래스를 인스턴스로 생성
fun main(){
var myCar1:Car = Car()
myCar1.color = "red"
myCar1.speed = 0
myCar1.upSpeed(50)
println(myCar1.speed)
var myCar2:Car = Car("black",0)
myCar2.upSpeed(250)
println(myCar2.speed)
}
- 정적 필드, 정적 메소드, 상수 필드 (Car클래스에 추가적으로 구현)
- companion object { } 안에 작성하여 정적 필드, 정적 메소드를 구현할 수 있음
companion object{
var carCount:Int = 0 //정적 필드
const val MAXSPEED:Int = 200 //상수 필드
const val MINSPEED:Int = 0
fun currentCarCount():Int{ //정적 메소드
return carCount
}
}
- 인스턴스를 생성하지 않고 클래스 자체에서 호출하여 사용 가능
println("생산된 차의 대수(정적 필드) ==> "+Car.carCount)
println("생산된 차의 대수(정적 메소드) ==> "+Car.currentCarCount())
println("차의 최고 제한 속도(상수 필드) ==>"+Car.MAXSPEED)
클래스 상속과 메소드 오버라이딩
- 오버라이딩: 슈퍼클래스의 메소드를 무시하고 새로 정의하는 것을 의미함
- 오버라이딩 할 때 자바와의 차이점 : 자바는 자식이 부모에게 오버라이딩을 허락받지 않고 자유롭게 정의할 수 있었지만 코틀린은 부모에 open키워드를 사용하여 오버라이딩을 허락해야함
open class Car{ //open키워드
...
open fun upSpeed(value:Int){ //open키워드
...
}
}
class Automobile:Car {
var seatNum:Int = 0
constructor(){}
fun countSeatNum():Int{
return seatNum
}
override fun upSpeed(value:Int){ //override하는 경우 부모클래스의 앞에 open키워드 지정
if(speed+value >= 300)
speed = 300
else
speed = speed + value
}
}
- 전체 코드
open class Car{ //부모클래스
var color:String = ""
var speed:Int = 0
companion object{
var carCount:Int = 0 //정적 필드
const val MAXSPEED:Int = 200 //상수 필드
const val MINSPEED:Int = 0
fun currentCarCount():Int{ //정적 메소드
return carCount
}
}
constructor(){} //default생성자
constructor(color:String, speed:Int){ //생성자 추가 (오버로딩)
this.color = color
this.speed = speed
carCount++
}
open fun upSpeed(value:Int){
if(speed+value >= 200)
speed = 200
else
speed = speed + value
}
fun downSpeed(value:Int){
if(speed-value <= 0)
speed = 0
else
speed = speed - value
}
}
class Automobile:Car { //자식클래스
var seatNum:Int = 0
constructor(){}
fun countSeatNum():Int{
return seatNum
}
override fun upSpeed(value:Int){ //override하는 경우 부모클래스의 앞에 open키워드 지정
if(speed+value >= 300)
speed = 300
else
speed = speed + value
}
}
fun main(){
var myCar1:Car = Car()
myCar1.color = "red"
myCar1.speed = 0
myCar1.upSpeed(50)
println(myCar1.speed)
var myCar2:Car = Car("black",0)
myCar2.upSpeed(250)
println(myCar2.speed)
println("생산된 차의 대수(정적 필드) ==> "+Car.carCount)
println("생산된 차의 대수(정적 메소드) ==> "+Car.currentCarCount())
println("차의 최고 제한 속도(상수 필드) ==>"+Car.MAXSPEED)
}
추상클래스와 추상메소드
- 추상클래스 : 인스턴스화를 금지하는 클래스
- 추상메소드 : 본체가 없는 메소드
- 추상클래스와 추상메소드는 앞에 abstract 키워드를 붙여서 지정할 수 있음
- 추상클래스/메소드를 사용하기 위해서는 자식 클래스에서 상속을 받아서 오버라이딩 해주어야함
- 사용목적 : 공통적으로 사용되는 기능을 추상 메소드로 선언 해놓고, 추상 클래스를 상속받은 후에 추상 메소드를 오버라이딩해서 사용하기 위함
abstract class Animal{ //추상클래스 구현 : abstract
val name:String=""
abstract fun move() //추상메소드 구현 : abstract + 함수내용 포함x
}
class Tiger:Animal(){ //추상클래스를 상속받음
var age:Int=0
override fun move(){ //추상메소드를 구현
println("네 발로 이동")
}
}
class Eagle:Animal(){
var home:String=zip()
override fun move(){
println("날개로 날아감")
}
}
fun main(){
var tiger = Tiger()
var eagle = Eagle()
tiger.move()
eagle.move()
}
다형성
- 서브클래스에서 생성한 인스턴스를 자신의 클래스 변수에 대입할 수 있는 것을 의미함
- 하나의 변수에 여러 종류의 인스턴스를 대입할 수 있음
fun main(){
var animal:Animal //부모클래스 변수 선언
animal = Tiger() //자식클래스 객체 생성 후 대입 가능 => 다형성
animal.move()
animal = Eagle()
animal.move()
}
인터페이스
- 추상클래스와 비슷함_그러나..
- 추상클래스는 필드를 가질 수 있지만 인터페이스는 필드를 가지지 못함
- 추상클래스는 추상메소드+일반메소드 모두 사용 가능하지만 인터페이스에는 추상메소드만 사용 가능
- interface 키워드를 사용하여 정의하고 내부에는 추상 메소드를 선언함
- 인터페이스는 ‘상속받는다’고 하지 않고 ‘구현한다’고 함
interface iAnimal{
abstract fun eat()
}
class iCat:iAnimal{
override fun eat(){
println("생선을 먹음")
}
}
- 전체코드
abstract class Animal{ //추상클래스 구현 : abstract
val name:String=""
abstract fun move() //추상메소드 구현 : abstract + 함수내용 포함x
}
interface iAnimal{
abstract fun eat()
}
class iCat:iAnimal{
override fun eat(){
println("생선을 먹음")
}
}
class Tiger:Animal(),iAnimal{ //추상클래스와 인터페이스를 상속받음
var age:Int=0
override fun move(){ //추상메소드를 구현
println("네 발로 이동")
}
override fun eat(){
println("뭐든 먹음")
}
}
class Eagle:Animal(){
var home:String=""
override fun move(){
println("날개로 날아감")
}
}
fun main(){
var animal:Animal
animal = Tiger()
animal.move()
animal.eat()
animal = Eagle()
animal.move()
var cat = iCat()
cat.eat()
}
람다식(lambda expression)
- 함수를 익명 함수(anonymous function) 형태로 간단히 표현 한 것
- 코드가 간결해져서 가독성이 좋아짐
- 람다는 { } 안에 매개변수와 메소드의 모든 내용을 선언
//일반적인 메소드형식
fun addNumber(n1:Int, n2:Int):Int{
return n1+n2
}
//람다식
val = addNumber = {n1:Int, n2:Int -> n1+n2}
람다식의 특징
① 람다식은 { }로 감싸며 fun 예약어를 사용하지 않음
② { } 안 ->의 왼쪽은 파라미터, 오른쪽은 함수의 내용
③ -> 오른쪽 문장이 여러 개라면 세미콜론(;)으로 구분
④ 내용 중 마지막 문장은 반환값(return)임
* 문자열 비교시 equals()말고도 ==연산자 사용 가능! (코틀린 완전 편하구낭)
날짜 형식
- DateFormat 클래스를 상속받은 SimpleDate Format 사용
- ‘연월일’이나 ‘시분초’와 같은 일반적인 표현이 가능함
import java.text.DateFormat
import java.util.*
import java.text.SimpleDateFormat
fun main(){
var now = Date()
var sFormat:SimpleDateFormat
sFormat = SimpleDateFormat("yyyy-MM-dd")
println(sFormat.format(now))
sFormat = SimpleDateFormat("HH:mm:ss")
println(sFormat.format(now))
}
'Android > Kotlin App' 카테고리의 다른 글
[Kotlin App] TabHost (0) | 2021.05.03 |
---|---|
[Kotlin App] 목록 대화상자 (0) | 2021.04.19 |
[Kotlin] ?(물음표)와 !!(느낌표 두개)의 사용 (0) | 2021.04.17 |
[Kotlin App] 메뉴 - 옵션메뉴, 컨텍스트 메뉴 (0) | 2021.04.16 |
[Kotlin App] 액티비티 / 인텐트 (0) | 2021.04.13 |
댓글