안드로이드 앱 개발 코틀린편. 객체지향 에서는
클래스의 기본
다형성
Abstract 추상 , Interface
DataClass
Object
에 대해서 다룰 것이다.
객체지향프로그래밍에서 interface와 abstract 를 이용한
다형성 프로그래밍이 중요하다.
2021.10.02 - [소프트웨어공학/디자인 패턴] - [디자인 패턴] 설계 원칙
디자인 패턴을 알고 간다면 더 좋은 효율적인 코드를 작성할 수 있을 것이다.
Class
간단한 코틀린 클래스
class Test1
{
var name : String = "Test1"
var age : Int = 10
// 세컨더리 생성자 (Secondary constructor)
constructor(){
println(this.toString())
}
constructor(name:String, age:Int)
{
this.name = name
this.age = age
}
fun showInfo() = println("${name} : ${age}")
}
Test1 : 10
용어
클래스의 변수 : 프로퍼티 (Property)
클래스의 함수 : 메소드 (Method)
java와 비교했을 때 생성자 부분이 많이 달라진다.
public class Test1
{
String name = "Test1";
int age = 10;
public Test1() {
System.out.println(this.toString());
}
public Test1(String name, int age) {
this.name = name;
this.age = age;
}
void showinfo(){
System.out.println(name + " : "+ age);
}
}
생성자를 클래스명() 으로 처리하는 클래스
클래스에서 다른 생성자를 정의하려면
contructor 뒤에 : this(정의한 값)을 덛붙인다.
class Test2(name:String) // 프라이머리 생성자
{
var name : String = "test2"
var age : Int = 20
init{ // 기본 생성자
this.name = name
}
constructor(name : String ,age : Int): this(name) // 세컨더리 생성자, Test2(name)
{
this.name = name
this.age = age
}
fun showInfo() = println("${name} : ${age}")
}
프라이머리 생성자 : class Test2(name : String)
기본 생성자 : init{ .. }
세컨더리 생성자 : constructor(name : String , age : int) : this(name)
상속을 위한 클래스 정의
open class ParentClass (msg : String)
{
var message = msg
fun sayHello() = println(message)
}
class ChildClass (msg : String) : ParentClass(msg) // -> 부모 생성자 호출
{}
java 버전
class SuperClass
{
String message;
SuperClass(String msg){
message = msg;
}
void sayHello(){
System.out.println(message);
}
}
public class ChildClass extends SuperClass
{
ChildClass(String msg) {
super(msg);
}
}
다형성
코틀린 에서의 오버로딩과 오버라이딩을 다룰 것이다.
- 상위 클래스에서 메소드와 필드를 open으로 정의
- 상속받은 클래스에서 override로 정의한다.
- 오버로딩은 자바와 같다. 같은 이름의 다른 파라미터를 받는 메소드를 정의
- 코틀린은 연산자 오버로딩을 제공한다.
open class BaseClass
{
open var name = "base"
open fun f1() = println(this.toString())
private fun onlyMyFunc() = println("BaseClass 내부에서만 사용")
constructor()
{
onlyMyFunc()
}
}
상속가능한 클래스를 구별하기 위해 open을 쓰는 듯
필드도 open으로 정의
class ChildClass : BaseClass()
{
// 오버라이드 , 재정의
override var name="child"
override fun f1() = println(this.toString()+" 를 재정의함")
// 오버로딩
fun f2() = println("f2")
fun f2(s : String) = println("f2 : $s")
}
코틀린에서의 상속
class ChildClass : BaseClass()
오버라이드 할때 override 로 정의
var obj1 = BaseClass()
obj1.f1()
var obj2 = ChildClass()
obj2.f1()
obj2.f2()
obj2.f2("문자형 파라미터")
BaseClass 내부에서만 사용
org.jetbrains.kotlin.idea.scratch.generated.ScratchFileRunnerGenerated$ScratchFileRunnerGenerated$BaseClass@5479e3f
BaseClass 내부에서만 사용
org.jetbrains.kotlin.idea.scratch.generated.ScratchFileRunnerGenerated$ScratchFileRunnerGenerated$ChildClass@66133adc 를 재정의함
f2
f2 : 문자형 파라미터
연산자 오버로딩
연산자 오버로딩은 C++에서 operator++ 과 같이 정의하였다.
java에서는 연산자 오버로딩을 사용할 수 없다.
class Student(s : String)
{
var name : String = s
var score : Int = 0
// 연산자 오버로딩
operator fun plus(student : Student) : Int{
return student.score + this.score
}
operator fun inc() : Student{
this.score++
return this
}
fun printMe() = println("${name}의 점수는 $score")
}
연산자 오버로딩을 통해 객체, 객체간 연산 가능
student++
student + student2
// 연산자 오버로딩 테스트
var student = Student("일모씨")
(0..99).forEach{student++} // 총 10번
student.printMe()
var student2 = Student("이모씨")
student2.score = 50
println("두 학생의 점수는 ${student + student2}")
<결과>
일모씨의 점수는 100
두 학생의 점수는 150
interface , abstract, static 구현
- interface : interface 이름 {} 으로 정의, 오버라이드하기 위해 open이나 기타 지시자 정의 X
- abstract class : 구현 상속할 메소드도 abstract로 정의 , 상속에서는 override로 정의
- static : 사용하려면 클래스 내에 companion object {} 를 만들고, 그 안에 멤버필드나 메소드 정의
interface
interface ITest{
fun testFunc()
}
class InterImp1 : ITest{
override fun testFunc() = println("InterImp1 testFunc()")
}
class InterImp2 : ITest{
override fun testFunc() = println("InterImp2 testFunc()")
}
fun main()
{
var whatYouWant = 1
var inter : ITest =
if(whatYouWant == 1) InterImp1()
else InterImp2()
// DIP
// 구현 클래스를 알 필요 없다.
interfaceTest(inter)
}
fun interfaceTest(pInter: ITest){
pInter.testFunc()
}
InterImp1 testFunc()
추상 클래스 + static (companion object)
abstract class
abstract class TestAbstract
{
fun testFunc() = println("abstract testFunc")
abstract fun abstractFunc()
}
class TestAbstractImp : TestAbstract()
{
override fun abstractFunc() = println("TestAbstractImp abstractFunc")
// static
//companion object {} 안에서 구현해야 static 가능
companion object
{
var staticVar = "companion staticVar"
fun staticFunc() = println("companion staticFunc")
}
}
fun main()
{
// 추상화
var obj = TestAbstractImp()
obj.testFunc() // 부모클래스 메소드
obj.abstractFunc() // 재정의된 메소드
println()
// static
println(TestAbstractImp.staticVar)
TestAbstractImp.staticFunc()
}
abstract testFunc
TestAbstractImp abstractFunc
companion staticVar
companion staticFunc
또 다른 예)
// 본래는 각 클래스 마다 파일 생성, 편의를 위해 한번에 생성함
// 1. 슈퍼클래스에서 상위 개념 정의
// Interface도 구현 가능
abstract class Animal {
abstract fun eat()
open fun showTool() : String {throw UnsupportedOperationException()}
}
// 2. 각 서브클래스에서 재정의/ 구현
class Human() : Animal()
{
lateinit var tool : String
constructor(tool: String) : this() {
this.tool = tool
}
override fun eat() {
println("밥을 먹음")
}
override fun showTool() : String{
return tool
}
}
class Cow : Animal()
{
override fun eat() {
println("풀을 먹음")
}
}
fun main()
{
// 3. 슈퍼 클래스 타입으로 참조변수 선언
val animalList = mutableListOf<Animal>()
animalList.add(Human("숟가락"));animalList.add(Cow())
println(animalList.get(0).showTool())
for (animal in animalList) animal.eat()
}
main()
<결과>
숟가락
밥을 먹음
풀을 먹음
자식 클래스에서 추상클래스 상속 받기 and 인터페이스 구현하는 방법
-- > class TestAbstractImp : TestAbstract(), ITest
여기까지 클래스(class), 객체지향(OOP), 다형성 (polymorphism)을 코틀린으로 실습해보았습니다.
디자인 패턴을 배우면서 다형성이 매우 중요다고 할 수 있습니다.
클래스의 변경( 추가, 변경 , 삭제) 이 자주 일어난다면 interface, abstract class 를 활용하여 다형성을 이용한 프로그래밍을 하는 것을 추천합니다.
추상클래스(abstract class) : 공유 연산이 많을 때(공유되는 코드가 많을 때 추상클래스) /
인터페이스(interface) (What to do) : 호출가능한 메소드 집합(interface) 을 Contract
concreate 클래스(How to do)
interface > 추상(abstract) > 구상(concrete)
Polymorphic Composition)
Composition of Abstraction(interface) (not Concretion) / 구현X -> 변경영향 적음
감사합니다.
fast campus - 올인원 패키지 : 안드로이드앱 개발
'Language > 코틀린' 카테고리의 다른 글
코틀린 kotlin 기초 문법 Restart (0) | 2024.02.23 |
---|---|
[Kotlin] Fast campus 강의 Android App 개발 (코틀린) 함수형 프로그래밍, .let .apply .run .also , Closure , 확장함수 , DSL , 커링(currying) (0) | 2021.10.24 |
[Kotlin] Fast campus 강의 안드로이드 앱 개발 (코틀린) data class, Object (0) | 2021.10.21 |
[Kotlin] Fast campus 강의 Android App 개발 (코틀린). 문법 (0) | 2021.10.16 |
[Kotlin] Fast campus 강의 내돈내산 Android App 개발 (코틀린). 시작 (0) | 2021.10.01 |
댓글