Teaching Strategy: C# Interfaces

👋 Hi Jordan!

Just like in Teaching Strategy: C# Classes, I start students off with a lightning exercise which eventually ends with problem, a conundrum, a puzzling vexation.

For this lesson, I start by telling the students that the end goal of this series of lightning exercises is to build a basic implementation of a flower shop that makes arrangements of flowers for two occassions: Mother's Day and birthdays.

Lightning Exercise 1

Create a new project, make a sub-directory named Models, and then touch a file in that directory named Rose.cs. I ask the students what they imagine would be some properties of a rose. They shout out ideas and I make applicable properties in a Rose class in that file.

namespace FlowerShop
{
    public class Rose
    {
        public string Color { get; set; }
        public int PetalCount { get; set; }
        public string Species { get; set; }
        public double StemLength { get; set; }
        public bool Thorny { get; set; }

        public override string ToString()
        {
            return $"A fanciful {Color} rose with {PetalCount} petals.";
        }
    }
}

Lightning Exercise 2

Ask students to create three more files in the Models, and put a class in each one, to represent 3 other flowers. They pick which ones they want to make.

Lightning Exercise 3

Create a file in the Models directory named FlowerShop.cs and have students create a class that implements a publicly accessible list of each flower type. For example...

public List<Rose> Roses { get; set; } = new List<Rose>();

Lightning Exercise 4

Refactor all of the flowers to meet these requirements from the flower shop owner.

  • Choose the two flowers you want to be in the Mother's Day arrangement and make sure both have a StemLength property. Any flower in this arrangement, even in the future, needs to have a stem length of 5 inches. This means that the StemLength property must exist on those flowers. It can optional on other flowers.
  • The other two flowers will be in the birthday arrangement. Flowers in the birthday arrangement will always have some white in them. That means that the Color property must be on flowers for that arrangement. It can be optional on other flowers.

Lightning Exercise 5

  1. A MakeMothersDayArrangement() method that returns a list containing a collection of the two flowers you chose for this arrangement.
  2. A MakeBirthdayArrangement() method that returns a list containing a collection of the two flowers you chose for this arrangement.

Tell them that they have 15 minutes to get that implemented. In reality, you're only going to give them enough time to make the file, write all the properties and methods, and then realize that they can't fulfill the requirements. Since lists, as they have learned up to this point, can only can contain one type of thing, they can't add both a Rose and a Tulip (or whatever they chose) to a list. It has to be one or the other.

This should only take 5 minutes.

The Reveal

"Oh darn. I guess our flower shop can't make arrangements since lists can't store both flowers. If only I could make them the same type, while still being able to refer to them as a Rose and a Tulip."

Luckily, there is a way is C# to add an additional, shared type to both flowers in each arrangement. Since there are rules for each type, or subset, of flower, we can specify those rules in something called an interface.

Creating the Rules

  1. Create a new sub-directory in your project named Interfaces.
  2. Create two files named IMothersDayFlower.cs and IBirthdayFlower.cs.

Interfaces/IMothersDayFlower.cs

namespace FlowerShop {
    public interface IMothersDayFlower {
        double StemLength { get; set; }
    }
}

Interfaces/IBirthdayFlower.cs

namespace FlowerShop {
    public interface IBirthdayFlower {
        string Color { get; set; }
    }
}

These interfaces are rules that some classes need to follow based on (a) business requirements, or (b) agreed-upon development team requirements. In this case, these interfaces are specifying business requirements from the customer.

Following the Rules

Now refactor the flower classes to implement the interfaces.

public class Rose : IMothersDayFlower {
    public double StemLength { get; set; }
}

public class Tulip : IMothersDayFlower {
    public double StemLength { get; set; }
}

public class Chrysanthemum : IBirthdayFlower {
    public string Color { get; set; }
}

public class DragonsBreath : IBirthdayFlower {
    public string Color { get; set; }
}

Note: Make sure you show them what happens when you delete the required property on one of the classes and then hover over te red squiggle to show the exception.

interface-not-implemented

Making the Arrangements

Now you can show them the pièce de résistance, how this allows them to add two different flowers to be in the same list.

public List<IMothersDayFlower> MakeMothersDayArrangement () {
    List<IMothersDayFlower> arrangement = new List<IMothersDayFlower>() {
        new Tulip() { Size = 5 },
        new Tulip() { Size = 6 },
        new Tulip() { Size = 7 },
        new Rose() { Size = 5 },
        new Rose() { Size = 5 },
    };

    return arrangement;
}

public List<IBirthdayFlower> MakeBirthdayArrangement () {
    List<IBirthdayFlower> arrangement = new List<IBirthdayFlower>() {
        new DragonsBreath() { Color = "Blue & White" },
        new DragonsBreath() { Color = "Red & White" },
        new DragonsBreath() { Color = "Blue & White" },
        new Chrysanthemum() { Color = "Purple & White"},
        new Chrysanthemum() { Color = "White" },
    };

    return arrangement;
}