Difference between Covariance & Contra-variance

前端 未结 5 1538
小鲜肉
小鲜肉 2020-11-22 10:20

I am having trouble understanding the difference between covariance and contravariance.

5条回答
  •  不知归路
    2020-11-22 10:56

    Co and Contra variance are pretty logical things. Language type system forces us to support real life logic. It's easy to understand by example.

    Covariance

    For instance you want to buy a flower and you have two flowers shop in your city: rose shop and daisy shop.

    If you ask someone "where is the flowers shop?" and someone tells you where is rose shop, would it be okay? Yes, because rose is a flower, if you want to buy a flower you can buy a rose. The same applies if someone replied you with the address of the daisy shop.

    This is example of covariance: you are allowed to cast A to A, where C is a subclass of B, if A produces generic values (returns as a result from the function). Covariance is about producers, that's why C# use keyword out for covariance.

    Types:

    class Flower {  }
    class Rose: Flower { }
    class Daisy: Flower { }
    
    interface FlowerShop where T: Flower {
        T getFlower();
    }
    
    class RoseShop: FlowerShop {
        public Rose getFlower() {
            return new Rose();
        }
    }
    
    class DaisyShop: FlowerShop {
        public Daisy getFlower() {
            return new Daisy();
        }
    }
    

    Question is "where is the flower shop?", answer is "rose shop there":

    static FlowerShop tellMeShopAddress() {
        return new RoseShop();
    }
    

    Contravariance

    For instance you want to gift a flower to your girlfriend and your girlfrend likes any flowers. Can you consider her as a person who loves roses, or as a person who loves daisies? Yes, because if she loves any flower she would love both rose and daisy.

    This is an example of the contravariance: you’re allowed to cast A to A, where C is subclass of B, if A consumes generic value. Contravariance is about consumers, that's why C# use keyword in for contravariance.

    Types:

    interface PrettyGirl where TFavoriteFlower: Flower {
        void takeGift(TFavoriteFlower flower);
    }
    
    class AnyFlowerLover: PrettyGirl {
        public void takeGift(Flower flower) {
            Console.WriteLine("I like all flowers!");
        }
    }
    

    You're considering your girlfriend who loves any flower as someone who loves roses, and giving her a rose:

    PrettyGirl girlfriend = new AnyFlowerLover();
    girlfriend.takeGift(new Rose());
    

    Links

    • Post about generic programming in general
    • The same answer for Java programming language

提交回复
热议问题