This essay says that inheritance is harmful and if possible you should “ban inheritance completely”. You see these arguments a lot, as well as things like “prefer composition to inheritance”. A lot of these arguments argue that in practice inheritance has problems. But they don’t preclude inheritance working in another context, maybe with a better language syntax. And it doesn’t explain why inheritance became so popular in the first place. I want to explore what’s fundamentally challenging about inheritance and why we all use it anyway.

  • John@mastodon.social
    link
    fedilink
    arrow-up
    16
    ·
    7 months ago

    @onlinepersona @armchair_progamer

    A type has a number of ‘inhabitants’. ‘Sum’ indeed corresponds to adding the possible inhabitants together.

    A Boolean has two inhabitants - true and false. A byte has 256 inhabitants. A BoolOrByte type has 258 inhabitants.

    If you have BoolByte pair, that’s a product type - 512 possible inhabitants.

    It may make no fucking sense depending on your exposure to Java, where Void (literally ‘empty’) has an inhabitant, and Boolean has 5.

      • John@mastodon.social
        link
        fedilink
        arrow-up
        3
        ·
        7 months ago

        @onlinepersona

        An enum is a sum type because the number of inhabitants of the enum is the sum of the inhabitants of its parts.

        A product type’s number of inhabitants is the product of its parts’ inhabitants. So a struct would fit that definition, or a pair, or a tuple.

        Looking at the pic on your Cartesian product link:
        if A is an enum {x,y,z} and B is an enum {1,2,3}, then a struct AxB has 9 possible inhabitants.

        • onlinepersona@programming.dev
          link
          fedilink
          English
          arrow-up
          4
          ·
          7 months ago

          OK, I think I’m getting it.

          A product is a set that this is the result of an ordered cartesian products.

          struct Car {
            make: String,
            model: String,
            seats: u8,
          } 
          

          Car = String X String x u8.


          An enum is a series of "or"s.

          enum Animal {
            Dog,
            Cat,
            Giraffe,
            Chimpanzee,
          }
          

          can also be thought of as Animal = Dog | Cat | Giraffe | Chimpanzee. Where Dog is a type that only has single value in its set aka Animal = {1} | {2} | {3} | {4}, but it could also be strings, or other objects. Rust however allows more complex objects:

          enum ComplexEnum {
              Nothing,
              Something(u32),
              LotsOfThings {
                  usual_struct_stuff: bool,
                  blah: String,
              }
          }
          

          In this case is Something(u32) the equivalent of any “tagged” u32, meaning in memory it’s something like a Tag + 32 bits where Tag is a constant string of bits, maybe itself a u32? Wouldn’t that make it a product type?
          But then LotsOfThings is itself a product type LotsOfThings = bool x String.

          So to put it all together ComplexEnum = Nothing | TaggedU32 | (bool x String)? Is that correct?

          Anti Commercial-AI license

          • arendjr@programming.dev
            link
            fedilink
            arrow-up
            3
            ·
            7 months ago

            So to put it all together ComplexEnum = Nothing | TaggedU32 | (bool x String)? Is that correct?

            Pretty much, yeah. But just be aware the tags are effectively unique constants, so each has only one value. For consistency I would write it as:

            ComplexEnum = Nothing | Something(u32) | LotsOfThings(bool x String)

            In this notation,Something(u32) could also be written as 1 x u32 because tags are constants.