Kotlin/Kotlin Language

[Udacity] Kotlin Bootcamp for Programmers - Classes

chattymin 2023. 1. 19. 19:34
728x90
반응형

1번 문제

Practice Time
Earlier, we created and filtered a list of spices. Spices are much better represented as objects than as simple strings. Because they are objects, we can perform different things with them - such as cooking.

To recap, let's make a simple Spice class. It doesn't do much, but it will serve as the starting point for the next practice.

Create class, SimpleSpice.
Let the class be a property with a String for the name of the spice, and a String for the level of spiciness.
Set the name to curry and the spiciness to mild.
Using a string for spiciness is nice for users, but not useful for calculations. Add a heat property to your class with a getter that returns a numeric value for spiciness. Use a value of 5 for mild.
Create an instance of SimpleSpice and print out its name and heat.

sol.

class SimpleSpice {
    var name = "curry"
    var spciness = "mild"

    val het: Int
        get() {return 5}

    var heat = when(spciness){
        "mild" -> 5
        else -> 0
    }
}

fun main() {
    var simpleSpice = SimpleSpice()
    println("name = ${simpleSpice.name}, heat = ${simpleSpice.heat}")
}

 

2번 문제

Practice Time
Let's improve our SimpleSpice class so that we can have various spices with different levels of spiciness.

Create a new class, Spice.
Pass in a mandatory String argument for the name, and a String argument for the level of spiciness where the default value is mild for not spicy.
Add a variable, heat, to your class, with a getter that returns a numeric value for each type of spiciness.
Instead of the list of spices as Strings you used earlier, create a list of Spice objects and give each object a name and a spiciness level.
Add an init block that prints out the values for the object after it has been created. Create a spice.
Create a list of spices that are spicy or less than spicy. Hint: Use a filter and the heat property.
Because salt is a very common spice, create a helper function called makeSalt().

sol.

class Spice(var name: String, var spciness: String = "mild") {
    var heat = when(spciness){
        "non" -> 1
        "mild" -> 3
        "hot" -> 5
        "spicy" -> 7
        "bomb" -> 10
        else -> 0
    }
    init {
        println("name = $name, spiciness = $spciness, heat = $heat")
    }
}

var spice = listOf<Spice>(
    Spice("salt", "non"),
    Spice("curry", "mild"),
    Spice("pepper", "hot"),
    Spice("ShinRamyeon", "spicy"),
    Spice("BuldakRamyeon", "bomb")
)

var spiceList = spice.filter { it.heat <= 5 }

fun makeSalt() = Spice("salt")

 

3번 문제

Practice Time
Let's talk about books for a moment, those heavy tomes of paper with printed letters.

Create a class, Book, with a title and an author.
Add a method, readPage(), that increases the value of a private variable, currentPage, by 1.
Create a subclass of Book; name it eBook.
eBook also takes in a format, which defaults to "text".
In eBooks, counting words makes more sense than pages. Override the readPage() method to increase the word count by 250,
the average number of words per page from typewriter days.

sol.

open class Book(var title: String, var auther: String) {
    var currentPage = 1
    open fun readPage(){
        currentPage++
    }
}

class eBook(title: String, auther: String, var format: String = "text"): Book(title, auther){
    private var wordsCount = 0
    override fun readPage() {
        wordsCount += 250
    }
}

 

4번 문제

Practice Time
Abstract and Interface
Let's go back to your spices. Make Spice an abstract class, and then create some subclasses that are actual spices.

It's easiest (organizationally) if you make a new package, Spices, with a file, Spice, that has a main() function.
Copy/paste your Spice class code into that new file.
Make Spice abstract.
Create a subclass, Curry. Curry can have varying levels of spiciness, so we don't want to use the default value, but rather pass in the spiciness value.
Spices are processed in different ways before they can be used. Add an abstract method prepareSpice to Spice, and implement it in Curry.
Curry is ground into a powder, so let's call a method grind(). However, grinding is something that's not unique to curry, or even to spices, and it's always done in a grinder. So we can create an Interface, Grinder, that implements the grind() method. Do that now.
Then add the Grinder interface to the Curry class.
Delegation
Using the provided code from the lesson for guidance, add a yellow color to Curry.

fun main (args: Array<String>) {
   delegate()
}

fun delegate() {
   val pleco = Plecostomus()
   println("Fish has has color ${pleco.color}")
   pleco.eat()
}

interface FishAction {
   fun eat()
}

interface FishColor {
   val color: String
}

object GoldColor : FishColor {
   override val color = "gold"
}

class PrintingFishAction(val food: String) : FishAction {
   override fun eat() {
       println(food)
   }
}

class Plecostomus (fishColor: FishColor = GoldColor):
       FishAction by PrintingFishAction("eat a lot of algae"),
       FishColor by fishColor
Create an interface, SpiceColor, that has a color property. You can use a String for the color.
Create a singleton subclass, YellowSpiceColor, using the object keyword, because all instances of Curry and other spices can use the same YellowSpiceColor instance.
Add a color property to Curry of type SpiceColor, and set the default value to YellowSpiceColor.
Add SpiceColor as an interface, and let it be by color.
Create an instance of Curry, and print its color. However, color is actually a property common to all spices, so you can move it to the parent class.
Change your code so that the SpiceColor interface is added to the Spice class and inherited by Curry.

sol.

abstract class Spice(val name: String, val spciness: String, color: SpiceColor) : SpiceColor by color {
    abstract fun prepareSpice()
}

class Curry(name: String, spciness: String, color: SpiceColor = YellowSpiceColor) : Spice(name, spciness, color), Grinder{
    override fun prepareSpice() {
        grind()
    }

    override fun grind() {}
}

interface Grinder{
    fun grind()
}

interface SpiceColor {
    val color: String
}

object YellowSpiceColor : SpiceColor {
    override val color = "Yellow"
}

 

5번 문제

Practice Time
Create a simple data class, SpiceContainer, that holds one spice.
Give SpiceContainer a property, label, that is derived from the name of the spice.
Create some containers with spices and print out their labels.

sol.

// I used Spice Class that I wrote before

class SpiceContainer (val spice: Spice){
    val label = spice.name
}

val SpiceList = listOf<SpiceContainer>(
    SpiceContainer(Spice("YellowCurry","mild")),
    SpiceContainer(Spice("RedCurry", "hot")),
    SpiceContainer(Spice("BlackCurry", "spicy"))
)

fun main() {
    for (curry in SpiceList) println(curry.label)
}

 

6번 문제

Practice Time
You used object in the previous lesson and quiz.

And now that you know about enums, here's the code for Color as an enum:

enum class Color(val rgb: Int) {
   RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF);
}
In SpiceColor, change the type of color from String to the Color class, and set the appropriate color in YellowSpiceColor.

Hint: The color code for yellow is YELLOW(0xFFFF00)
Make Spice a sealed class.

What is the effect of doing this?
Why is this useful?

sol.

enum class Color(val rgb: Int) {
    RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF), YELLOW(0xFFFF00);
}

interface SpiceColor {
    val color: Color
}

object YellowSpiceColor : SpiceColor {
    override val color = Color.YELLOW
}

sealed class Spice1{
    class Curry(var name: String, var spciness: String) : Spice1()
    class Pepper(var name: String, var spciness: String) : Spice1()
    class Salt(var name: String, var spciness: String) : Spice1()
    class RedCurry(var name: String, var spciness: String) : Spice1()
}
// What is the effect of doing this? : sealed는 일종의 추상 클래스이다. 그렇기 때문에 세부 값이 일부 조정되더라도 새로 만들어 줄 필요 없이
// 해당 부분을 수정해서 선언하기만 하면 된다.
// Why is this useful? : sealed 클래스의 서브 클래스 각각에 대해 여러 개의 인스턴스 생성이 가능하다.
// 그렇기 때문에 상태값을 유동적으로 변경할 수 있다.
728x90
반응형