Start learning free

LESSON 563 OF 573 · OBJECT-ORIENTED PROGRAMMING - CHALLENGES

Shipping Options in Scala: Overriding Methods

Practice O(1) Read the full explanation

An online shop offers three ways to ship a parcel. Standard shipping is the basic one. Express and Economy are kinds of shipping too: they answer the same two questions, what the option is called and what it costs, but each in its own way. So each one overrides the parent's methods with its own versions.

Implement the class Shipping, the standard option:

  • name() returns "Standard".
  • cost(weight) returns 5 + weight: a base price of 5, plus 1 for each kilogram.

and two classes that inherit from Shipping and override both methods:

  • Express: name() returns "Express", and cost(weight) returns 10 + 2 * weight.
  • Economy: name() returns "Economy", and cost(weight) returns 3 plus half the weight, rounded down to a whole number: half of 7 is 3.

The input lists parcels, one per line: the option (standard, express or economy) and the weight. For each line, the code that tests your classes creates that option and prints <name>: <cost> from its name() and cost(weight). The two calls are the same for every option (where variables have types, through a variable of the parent type Shipping); because the methods are overridden, each option answers with its own version. The starter code spells these names the way your language does.

 

Example 1:

Input:
    standard 4
    express 4
    economy 4
Output:
    Standard: 9
    Express: 18
    Economy: 5
Explanation: The same parcel of 4 kilograms costs 5 + 4 = 9 with Standard, 10 + 2 × 4 = 18 with Express
and 3 + 2 = 5 with Economy (half of 4 is 2).

Example 2:

Input:
    standard 0
    express 0
    economy 0
Output:
    Standard: 5
    Express: 10
    Economy: 3
Explanation: With a weight of 0, only the base prices are left.

Example 3:

Input:
    economy 7
    economy 1
    standard 7
    express 7
Output:
    Economy: 6
    Economy: 3
    Standard: 12
    Express: 24
Explanation: Economy halves the weight and rounds down: half of 7 is 3, so 3 + 3 = 6, and half of 1 is 0, so 3 + 0 = 3.

 

Constraints:

  • 0 <= weight <= 1000, a whole number of kilograms.
  • At most 100 parcels per test case.
STEP 1 OF 6
    Ctrl + Enter to check

    SCALA · OBJECT-ORIENTED PROGRAMMING - CHALLENGES

    Shipping Options in Scala, explained

    Problem overview

    A shop offers three ways to ship a parcel. Shipping is the standard option, and Express and Economy are special kinds of shipping. Each answers the same two questions, name() and cost(weight), in its own way.

    • Shipping: the name is "Standard" and the cost is 5 + weight.
    • Express: the name is "Express" and the cost is 10 + 2 * weight.
    • Economy: the name is "Economy" and the cost is 3 + weight / 2.

    For a 4 kilogram parcel the three options cost 9, 18 and 5. With a weight of 0 only the base prices are left: 5, 10 and 3.

    Inheritance and overriding

    A class can extend another class. class Express extends Shipping says that an Express is a kind of Shipping: it gets every method of Shipping and may replace some of them. Replacing a method is called overriding. The new method has the same name and the same parameter and return types as the parent's, and Scala requires the keyword override in front of it.

    Here, Express and Economy override both methods. If Express left out cost, an express parcel would get the parent's price, 5 + weight.

    The useful part is that the version that runs depends on the object, not on the type of the variable that holds it. A Shipping variable can hold an Express, and calling name() on it still runs the express version.

    Step by step

    1. Write Shipping.name so that it returns "Standard".
    2. Write Shipping.cost so that it returns 5 + weight.
    3. In Express, write name with override and return "Express".
    4. In Express, override cost and return 10 + 2 * weight.
    5. In Economy, override name and return "Economy".
    6. In Economy, override cost and return 3 + weight / 2.

    Each class changes only itself. Overriding in Express has no effect on Shipping or Economy.

    The solution in Scala

    class Shipping {
        def name(): String = {
            return "Standard"
        }
    
        def cost(weight: Int): Int = {
            return 5 + weight
        }
    }
    
    class Express extends Shipping {
        override def name(): String = {
            return "Express"
        }
    
        override def cost(weight: Int): Int = {
            return 10 + 2 * weight
        }
    }
    
    class Economy extends Shipping {
        override def name(): String = {
            return "Economy"
        }
    
        override def cost(weight: Int): Int = {
            return 3 + weight / 2
        }
    }
    

    Details worth knowing:

    • Whole-number division. weight is an Int, so weight / 2 drops the remainder. With weight = 7 it gives 3, and the Economy cost is 6.
    • The empty parentheses. The methods are declared as name() and cost(weight: Int), and an overriding method must match the declaration of the method it replaces.
    • return. The solution writes return explicitly. In Scala the last expression of a method is its result anyway, so "Standard" alone would also do.

    Trying it

    Create each option in a variable of the parent type and call the same two methods on all of them:

    val options: List[Shipping] = List(new Shipping(), new Express(), new Economy())
    for (option <- options) {
      println(option.name() + ": " + option.cost(4))
    }
    

    This prints:

    Standard: 9
    Express: 18
    Economy: 5
    

    The loop never asks which class each option is. Other weights give these results:

    • Economy with weight 7 gives Economy: 6, and with weight 1 gives Economy: 3.
    • Standard with weight 0 gives Standard: 5, and Express with weight 0 gives Express: 10.
    • Economy with weight 1000 gives Economy: 503.

    Why override instead of branching

    Without inheritance, the code that prints a quote would need an if on the option: if it is express, use one formula; if it is economy, use another. Every new option would mean editing that code. With overriding, the decision is made once, by the object. The caller writes option.cost(weight) and each class supplies its own rule. Adding a fourth option means writing one more class that extends Shipping, and nothing that already works has to change.

    It also explains why the parent has real bodies and not placeholders. Shipping is a complete, usable option: the standard one. The other two start from it and replace what differs. A subclass that overrides nothing behaves exactly like its parent.

    Reading a call

    Take val option: Shipping = new Express() and the call option.cost(3). The variable's type is Shipping, so the compiler accepts any method that Shipping has. At run time the object is an Express, so the express version runs and the result is 10 + 2 * 3 = 16.

    Edge cases

    A weight of 0 is allowed, and it exposes only the base price of each option: 5, 10 and 3. The largest weight is 1000 kilograms, where Economy costs 3 + 500 = 503. Every value stays tiny compared with the limit of an Int, so overflow is not a concern. The one case that needs care is an odd weight in Economy: 7 / 2 is 3, not 3.5, because both numbers are Int, so the half kilogram is dropped.

    Another small trap is the order of operations in Express. In 10 + 2 * weight the multiplication happens first, which is what the rule asks for. Writing (10 + 2) * weight would be a different formula.

    Common mistakes

    • Forgetting override. Writing def name(): String in Express without the keyword is a compile error: method name of type (): String needs `override` modifier.
    • Changing the signature. A method with a different parameter type is a new method, not an override. Keep cost(weight: Int): Int exactly as it is in the parent.
    • Dividing at the wrong place. Economy's formula is 3 + weight / 2. Rounding happens only in the division, so 7 kilograms cost 3 + 3 = 6.
    • Mixing up the base prices. Standard starts at 5, Express at 10 and Economy at 3. A weight of 0 shows them directly.
    Keep going with Scala500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free