.
.
.
아래는 Person 클래스를 객체화해서 자기소개하는 코드이다.
// 클래스 정의
class Person(val name: String, var age: Int, var mbti: String) {
fun sayHello() {
println("안녕하세요, 저는 ${name} 입니다.")
}
fun increaseAge() {
age++
}
}
fun main() {
// 클래스를 객체화하여 객체 생성
val person1 = Person("Alice", 25, "ESTP")
val person2 = Person("Bob", 30, "ISTJ")
// 객체의 속성과 메서드 사용
println("${person1.name}의 나이는 ${person1.age}세, MBTI는 ${person1.mbti}입니다.")
person1.sayHello()
println("${person2.name}의 나이는 ${person2.age}세, MBTI는 ${person2.mbti}입니다.")
person2.sayHello()
// 객체의 속성 변경
person1.mbti = "ENTP"
println("${person1.name}의 나이는 ${person1.age}세, MBTI는 ${person1.mbti}입니다.")
// 객체의 메서드 호출
person2.increaseAge()
println("${person2.name}의 나이는 ${person2.age}세, MBTI는 ${person2.mbti}입니다.")
}
Person이라는 클래스를 정의했다.
이 클래스는 세 가지 속성 (이름(name), 나이(age), mbti),
두 가지 메서드 (sayHello(), increaseAge()를 가진다.
main() 함수에서 Person 클래스를 기반으로 두 개의 객체를 생성했다.
person1과 person2는 Person 클래스의 인스턴스, 각자 고유한 이름과 나이, mbti를 가진다.
객체를 생성하면 해당 객체의 속성과 메서드를 사용할 수 있다.
person1과 person2의 이름, 나이, mbti를 출력하고,
sayHello() 메서드를 호출하여 각 객체가 자기 소개를 할 수 있다.
객체의 속성은 .(도트 연산자)를 사용하여 접근하고, 메서드도 .를 사용하여 호출한다.
val 를 이용했기때문에 객체의 속성은 변경 가능하다.
person1.mbti = ENTP 처럼 mbti를 변경할 수 있고,
person2.increaseAge()와 같이 메서드를 호출하여 나이를 증가시킬 수도 있다.
.
.
.
다음은 Character 클래스를 이용하여 게임 캐릭터를 설정하는 코드이다.
fun main() {
// 불마법사로 객체화
var magicianOne = Character("불마법사", "red", 180.2)
println("${magicianOne.name}의 머리색상은 ${magicianOne.hairColor}입니다")
magicianOne.fireBall()
// 냉마법사로 객체화
var magicianTwo = Character("냉마법사", "blue", 162.2, 25, "여")
println("${magicianTwo.name}의 머리색상은 ${magicianTwo.hairColor}이고 나이는 ${magicianTwo.age}입니다.")
magicianTwo.fireBall()
}
class Character {
var name:String = ""
var hairColor:String = ""
var height:Double = 0.0
var age:Int = 0
var gender:String = ""
// 명시적 생성자 (Constructor)
// _name, _hairColor, _height와 같이 생성자에 변수를 넘기는 경우에 사용함
constructor(_name:String, _hairColor:String, _height:Double) {
println("이름 : ${_name}")
println("머리 색상 : ${_hairColor}")
println("키 : ${_height}")
name = _name
hairColor = _hairColor
height = _height
}
// _name, _hairColor, _height, _age, _gender와 같이 생성자에 변수를 넘기는 경우에 사용함
constructor(_name:String, _hairColor:String, _height:Double, _age:Int, _gender:String) {
println("이름 : ${_name}")
println("머리 색상 : ${_hairColor}")
println("키 : ${_height}")
println("나이 : ${_age}")
println("성별 : ${_gender}")
name = _name
hairColor = _hairColor
height = _height
age = _age
gender = _gender
}
fun gameStart() {
println("게임 시작")
}
}
캐릭터 속성을 저장하는 변수는 총 5개이다. (이름, 머리색상, 키, 나이, 성별)
Character 클래스에는 두 개의 생성자가 있다. 이 생성자는 객체가 생성될 때 호출된다.
첫 번째 생성자는 name, hairColor, height를 매개변수로 받는다.
이를 통해 캐릭터의 이름, 머리 색상, 키를 초기화하고
두 번째 생성자는 이름, 머리 색상, 키, 나이, 성별을 초기화한다.
main 함수에서 프로그램을 시작하며, 두 캐릭터 객체가 생성되고 사용된다.
.
.
var magicianOne = Character("불마법사", "red", 180.2)
를 통해 불마법사라는 이름의 Character 객체를 생성했고,
생성자의 매개변수를 통해 이름은 "불마법사", 머리 색상은 "red", 키는 180.2로 초기화했다.
println("${magicianOne.name}의 머리색상은 ${magicianOne.hairColor}입니다")
를 통해 magicianOne 객체의 이름, 머리 색상 출력
마지막으로, magicianOne.gameStart()를 호출하여
gameStart() 메서드를 실행하고 "게임시작!"이 출력된다.
.
.
var magicianTwo = Character("냉마법사", "blue", 162.2, 25, "여")
를 통해 냉마법사라는 이름의 Character 객체를 생성했고,
생성자의 매개변수를 통해 이름은 "냉마법사", 머리 색상은 "blue", 키는 162.2, 나이는 25,
성별은 "여"로 초기화했다.
println("${magicianTwo.name}의 머리색상은 ${magicianTwo.hairColor}이고 나이는 ${magicianTwo.age}입니다.")
를 통해 magicianTwo 객체의 이름, 머리 색상, 나이를 출력
마지막으로, magicianOne.gameStart()를 호출하여
gameStart() 메서드를 실행하고 "게임시작!"이 출력된다.
이처럼 객체 생성, 사용은 객체지향 프로그래밍의 핵심 개념 중 하나이다.
객체는 프로그램에서 데이터와 기능을 캡슐화하고 모듈화하는데 유용하며,
가독성과 유지보수 향상에 기여한다.
.
.
.
.
.
아래 코드는 디저트 주문 코드이며, 상속 관계를 가지는 클래스들로 구성되어있다.
fun main() {
var dessert = Dessert("디저트")
var cake = Cake("케이크")
var cookie = Cookie("쿠키")
var icecream = Icecream("아이스크림")
dessert.order()
cake.order()
cookie.order()
icecream.order()
}
open class Dessert(name:String) {
var name: String = ""
init {
// this는 현재 클래스의 상태변수를 의미합니다
// var name: String = ""
this.name = name
}
fun order() {
println("${name}이 주문이 접수되었습니다.")
}
}
class Cake(name: String) : Dessert(name) {
}
class Cookie(name: String) : Dessert(name) {
}
class Icecream(name: String) : Dessert(name) {
}
main 함수
main 함수에서 Dessert, Cake, Cookie, Icecream 클래스의 객체들을 생성하고,
order() 메서드를 호출하여 디저트 주문 동작을 출력한다.
Dessert 클래스
Dessert 클래스는 다른 디저트들이 상속을 받을 기반이 되며,
멤버변수 name, order() 메서드를 가진다.
멤버 변수 : name(디저트 이름을 저장하는 문자열 변수)
생성자: Dessert 클래스의 생성자는 name을 매개변수로 받아서 name 멤버 변수를 초기화
메서드: order() 메서드는 Dessert 클래스에 정의된 함수이다. 디저트를 주문하는 동작을 나타내며, 드저트 이름을 포함한 메시지를 출력한다.
생성자: 이 클래스들은 각각의 이름을 매개변수로 받아서, 상위 클래스인 Dessert의 생성자를 호출하여 name 멤버 변수를 초기화한다.
.
.
.
이 예제에서는 상속의 개념을 활용하여 공통적인 특성과 동작을 가지는 Dessert 클래스를 정의하고, Cake, Cookie, Icecream 클래스가 이를 상속받는다. 후에 자신만의 특성을 추가할 수도 있다.
상속 개념을 활용하면, 코드의 재사용성과 확장성이 높아지며,
상위 클래스 메서드인 Order()를 서브 클래스에서 그대로 사용하거나,
재정의(오버라이딩)하여 동작을 바꿀 수 있다.
.
.
.
.
.
OOP관점에서는 클래스들간의 관계를 만들고, 일관성을 유지하는 것이 목표!
만약 필요한 기능이 있을때마다 별도의 이름으로 만들게된다면
프로그램에 문제가 생기지는 않지만, 일관성 해치며 재사용성이 떨어져 유지보수가 어려움.
아래 코드는 디저트 주문 코드이며, 상속과 오버라이딩 개념을 가지는 클래스들로 구성되어있다.
fun main() {
var dessert = Dessert("디저트")
var cake = Cake("케이크", 2)
var cookie = Cookie("쿠키", "초코칩")
var icecream = Icecream("아이스크림", "바닐라")
dessert.order()
cake.order()
cookie.order()
icecream.order()
}
open class Dessert(name:String) {
var name: String = ""
init {
// this는 현재 클래스의 상태변수를 의미합니다
// var name: String = ""
this.name = name
}
open fun order() {
println("${name}를 선택했습니다.")
}
}
class Cake(name: String, count: Int) : Dessert(name) {
var count:Int = 0
init {
this.count = count
}
override fun order() {
// super객체는 부모의 객체를 의미하며 자동으로 생성됨
// 즉 부모객체의 fly메소드를 부르는 행위임
// 필요없으니 주석처리완료
// super.order()
println("${count}개의 ${name}를 주문했습니다.")
}
}
class Cookie(name: String, cookieFlavor: String) : Dessert(name) {
var cookieFlavor:String = ""
init {
this.cookieFlavor = cookieFlavor
}
override fun order() {
// super객체는 부모의 객체를 의미하며 자동으로 생성됨
// 즉 부모객체의 fly메소드를 부르는 행위임
// 필요없으니 주석처리완료
// super.order()
println("${cookieFlavor} ${name}를 주문했습니다.")
}
}
class Icecream(name: String, icecreamFlavor: String) : Dessert(name) {
var icecreamFlavor: String = ""
init {
this.icecreamFlavor = icecreamFlavor
}
override fun order() {
// super객체는 부모의 객체를 의미하며 자동으로 생성됨
// 즉 부모객체의 fly메소드를 부르는 행위임
// 필요없으니 주석처리완료
// super.order()
println("${icecreamFlavor} ${name}를 주문했습니다.")
}
}
Chicken, Sparrow, Pigeon 클래스에서는 drder() 메서드를 오버라이딩한다. 각각의 클래스에 적합한 동작을 추가하여 디저트 이름과 추가 특성을 출력한다. 오버라이딩된 order() 메서드는 super.order()를 호출하지 않고 직접 새의 이름과 추가적인 특성을 출력한다.
.
.
.
.
.
fun main() {
var calc = Calculator()
var intResult = calc.add(1,2)
var doubleResult = calc.add(1.2, 2.2)
println("정수 덧셈결과: ${intResult}")
println("실수 덧셈결과: ${doubleResult}")
}
class Calculator {
fun add(num1: Int, num2: Int): Int {
return num1+num2
}
fun add(num1: Double, num2: Double): Double {
return num1+num2
}
}
main 함수에서는, Calculator 클래스의 객체 calc를 생성한 후, add 메서드를 호출하여
두 개의 정수 1과 2를 더한 결과를 intResult 변수에 저장하고,
두 개의 실수 1.2와 2.2를 더한 결과를 doubleResult 변수에 저장한다.
println 함수로 정수 덧셈 결과와, 실수 덧셈 결과를 출력합니다.
Calculator 클래스에는 두 가지 add 메서드가 오버로딩되어 있다. 매개변수의 타입이나 개수가 다르기 때문에, 같은 이름의 메서드를 사용할 수 있다.
add(num1: Int, num2: Int): Int
정수형 매개변수 두 개를 받아서 덧셈 연산을 수행하고, 정수형 결과를 반환한다.
add(num1: Double, num2: Double): Double
실수형 매개변수 두 개를 받아서 덧셈 연산을 수행하고, 실수형 결과를 반환한다.
add 메서드는 매개변수의 타입에 따라 오버로딩되어, 정수형 매개변수를 받는 경우와 실수형 매개변수를 받는 경우에 각각 다른 덧셈 연산을 수행한다.
.
.
.
.
.
interface 인터페이스이름 {
fun 메소드이름()
}
interface HandmadeDessert {
fun cook()
// fun cook() {
// println("조리를 시작합니다.")
// }
}
interface HandmadeDessert{
fun cook()
}
fun main() {
var dessert = Dessert("디저트")
var cake = Cake("케이크", 2)
var cookie = Cookie("쿠키", 초코칩")
var icecream = Icecream("아이스크림", "바닐라")
var tteokbokki = Tteokbokki("떡볶이")
dessert.order()
cake.order()
cookie.order()
icecream.order()
tteokbokki.cook()
}
open class Dessert(name:String) {
var name: String = ""
init {
// this는 현재 클래스의 상태변수를 의미합니다
// var name: String = ""
this.name = name
}
open fun order() {
println("${name}를 선택했습니다.")
}
}
class Cake(name: String, count: Int) : Dessert(name) {
var count:Int = 0
init {
this.count = count
}
override fun order() {
println("${count}개의 ${name}를 주문했습니다.")
}
}
class Cookie(name: String, cookieFlavor: String) : Dessert(name) {
var cookieFlavor:String = ""
init {
this.cookieFlavor = cookieFlavor
}
override fun order() {
println("${cookieFlavor} ${name}를 주문했습니다.")
}
}
class Icecream(name: String, icecreamFlavor: String) : Dessert(name) {
var icecreamFlavor:String = ""
init {
this.icecreamFlavor = icecreamFlavor
}
override fun order() {
println("${icecreamFlavor} ${name}를 주문했습니다.")
}
}
class Tteokbokki(name: String) : Dessert(name), WaterBirdBehavior {
override fun cook() {
println("${name}를 주문했습니다. 조리를 시작합니다.)
}
}
.
.
.
open class Dessert(name:String) {
var name: String = ""
init {
// this는 현재 클래스의 상태변수를 의미합니다
// var name: String = ""
this.name = name
}
open fun order() {
println("${name}를 선택했습니다.")
}
}
Dessert 클래스의 name 프로퍼티는 디저트의 이름을 나타낸다.
생성자에서 name을 받아 해당 프로퍼티를 초기화하고
order() 함수는 디저트를 주문을 수행한다.
class Cake(name: String, count: Int) : Dessert(name) {
var count: Int = 0
init {
this.count = count
}
override fun order() {
println("${count}개의 ${name}를 주문했습니다.")
}
}
Cake 클래스는 Dessert 클래스를 상속받아서 만들어진 클래스로, count 프로퍼티를 이용하여 개수를 나타낸다.
생성자에서 name과 count를 받아 각각의 프로퍼티를 초기화하고, order() 함수를 오버라이드하여 케이크 주문 동작을 출력한다. Cookie 클래스, Icecream 클래스 모두 Cake 와 구조가 동일하다.
class Tteokbokki(name: String) : Dessert(name), HandmadeDessert {
override fun cook() {
println("${name}를 주문했습니다. 조리를 시작합니다.")
}
}
Tteokbokki 클래스는 Dessert 클래스를 상속받아 만들어진 클래스이며, HandmadeDessert 인터페이스를 구현하고 있다. cook() 함수를 구현하여 떡볶이 조리 동작을 출력한다.
interface HandmadeDessert {
fun cook()
}
cook() 함수를 선언하는 HandmadeDessert 인터페이스이다. 이 인터페이스를 구현하는 클래스들은 cook() 함수를 반드시 실행한다.
fun main() {
var dessert = Dessert("디저트")
var cake = Cake("케이크", 2)
var cookie = Cookie("쿠키", "초코칩")
var icecream = Icecream("아이스크림", "바닐라")
var tteokbokki = Tteokbokki("떡볶이")
dessert.order()
cake.order()
cookie.order()
icecream.order()
tteokbokki.cook()
}
main 함수에서는 Dessert, Cake, Cookie, Icecream, Tteokbokki 클래스의 객체들을 생성하고 각각의 order() 또는 cook() 함수를 호출한다. 출력은 아래와 같다.
.
.
.