In D programming language, classes support single inheritance (a class can derive from only one parent class) while supporting multiple interfaces (a class can implement multiple interfaces). This allows developers to create hierarchical type relationships where derived classes inherit properties and behaviors from base classes, while also adhering to interface contracts that define common behaviors. The language provides runtime type information through typeid and typeof operators, enabling runtime polymorphism where objects of different types can be stored in collections of a base class type. Access modifiers (public, private, protected) control visibility, with public being the default and everything being public to the module by default.
Deep Dive
Prerequisite Knowledge
- No data available.
Where to go next
- No data available.
Deep Dive
Classes - single inheritance multiple interfaces - part 4 of N [D Language - Dlang Episode 143]Added:
Hey, what's going on folks? This is Mike here and welcome back to my D programming language series. In today's episode we're going to be talking about inheritance as it's related to classes.
So, with that said, let's go ahead and dive on to the D programming language website here, into documentation, the language reference, and into classes.
Now, again, when we were first learning about classes in one of the earlier videos, so make sure you checked out the earlier videos, uh we learned again classes are basically D's solution for object-oriented programming. So, they're again different from structs. We've again covered that in a previous video, so make sure you check out that playlist there. Uh but the basic idea is for classes, where we're defining our own type here, uh we have the ability to perform inheritance through classes. Now, again, D supports single inheritance, uh so no multiple inheritance, uh and that's basically the way to extend a type. But everything sort of lives within the same family. So, what do I mean by that?
Let's just go ahead to the whiteboard here. So, if you're not familiar with this idea here, uh let's just go ahead and draw this out. And basically, what that means is we might have some base class here. Uh let's go ahead and make this a little bit different here. There we go, base class.
And we'll have sort of a hierarchical relationship here, meaning I can derive a new type here. So, we'll have derived here.
And as an example, the classic example is here, maybe we'll have a dog. It'll have some functionality here. So, let's just add some functionality like, uh for instance, it can uh bark.
It can run, you know, some common things here. But then what what if I derive another type of dog here, uh maybe a husky, for instance, and we'll want to override how this dog runs here. Okay, so we'll override, and I'll write that out here, how it runs. And that's the basic idea. Then I can derive something else here, um from dog, another type of dog here, and pick your favorite, maybe a golden retriever here, and maybe we change how that dog uh barks, for instance. Okay? But it has the default sort of implementation of whatever the run is here. Okay?
And these here that I'm defining, these are classes uh that I'm going to be using today. And we can still combine in the idea of an interface that we learned about last time. So, let's just say we have some other interface here for things that maybe animals can do.
And I'll just label it as interface.
Sorry, I will squeeze in that writing here. And maybe there are again things that all of them can do.
Uh let's see, we have running, we have barking, and let's just add, I don't know, walking, something like that. So, we can equally have each of these uh either at the top of the hierarchy uh use or inherit to this interface, and then by default, that means everything else will have to inherit this interface. Or we can be more selective, and what if we say only uh goldens, for instance, or for whatever reason, can walk, then we can also perform uh just a uh sort of uh adherence to this interface from our golden class. Okay? So, we'll look at a few of these scenarios, so we can see how all the tools work together.
Uh and I think for today, we're just going to go ahead and um dive into the code for the most part here.
Um let me see if there's anything else related to inheritance uh that we can kind of queue up here.
Um yeah, we'll kind of get to this idea.
Again, just want to emphasize again, multiple class inheritance is not supported, but you can have again multiple interfaces. I think we touched on that in one of the previous lessons already, as well.
Uh and then again, by default, uh as was also mentioned, everything is a type of object. Um so, again, that's sort of similar if you're coming from a Java world, uh D has that same sort of uh idea here.
Okay? So, if you just wanted a generic collection of stuff, um objects, classed class-based objects, uh you can do that with objects. And again, D knows the runtime type information here. So, I'll actually show you so you can figure out am I looking at class A, class B, uh what exactly am I looking at? Okay? So, anyways, we'll get into this. So, let's go ahead and uh let's just dive into the uh code editor here.
Um and we'll take a look at this cuz um I think we got a few neat things uh to show you here. So, let's uh start with um an example. We'll make this a little bit concrete. Let's use um Ooh, just to make it fun, let's use monster as sort of our base class here. Uh I'll give you a note here. Our base class or sometimes the superclass, okay? Uh and we're going to see this keyword super come up. I'm going to use it a little bit more in probably the next video here. Uh but again, that's the sort of the highest-level thing on the hierarchy, right? That's what we were showing here uh when I mean highest-level thing on the hierarchy, okay? And maybe we draw these arrows pointing up to show that we're deriving from uh our uh the drive class drives from the base class, okay?
Um all right. So, anyways, let's go ahead and continue on with our monsters.
And let's go ahead and create some base class here like a dragon.
And it's going to be a type of monster.
And simple as that here, okay? Just the colon and then the type that we have here. Um And we can go ahead and compile that.
That works here. Um again, if you're coming from other languages, you know, maybe you're like, "Well, what if I put public there or something?" Uh yeah, we don't really do uh that type of thing here, right? We just sort of derive uh from it here, okay? Uh let's say monsters, they all have certain attributes here like their power and their health, for instance.
And then if I uh I basically uh can derive from uh monster here into my dragon, I also have these attributes here. So, I'm going to put in comments just so we see here um the public Let's see, public attributes uh are uh available. Public or protected uh attributes are available. So, we effectively have power and health here. Okay?
Uh and that's the idea. And the way that we talk about dragon, if you're not familiar with inheritance, is dragon uh is a type of monster. Okay?
Uh so, again, that's the the idea here.
So, now what I can do is, for instance, if I have just an array of monsters here, I can do something like monster, and I can append to it a new dragon, right?
Because, well, anything that is a type of monster belongs in this collection, and that includes dragons here. Okay?
So, that is the idea. Let's go ahead and compile that just to make sure we're in good uh state here. Uh oh, what did I do here? Monsters.
There we go.
With yes. Okay, so that is compiling code and our first uh class here that we can be happy with.
Now, um let's play around with this just a little bit here, cuz we've sort of talked about these public attributes here. What if I made this uh private here? Okay?
Uh and let's make this private here.
And okay, so that's that's good news.
And let's go ahead and make a maybe a constructor here.
Uh I'm just going to say int p and h.
And let's assign these. Power equals p, health equals uh h.
And I'm effectively just going to copy this constructor over to the dragon here. Okay? And what I want to be teaching us about is these uh attributes and how these accessories work when we're doing uh inheritance. So, let's go ahead and try this out.
And uh let's see what's happening here.
Okay, error. Constructor. Okay, so however we're creating our dragon, that's illegal.
All right, we've defined a destructor. I mean, by default we get a implicit constructor for us. So, I need to say the power I'm calling this constructor here is five and the health is I don't know, eight here. Maybe it's a pretty weak dragon here.
Okay, so now what's going on here?
Error, constructor main.dragon.this no match for this implicit super call in the constructor. Okay.
What does this mean here? Well, in order to derive this new class, because dragon is a type of monster, I need to also construct the monster here. So, it's saying, "Hey, there's no How do I call the, you know, sort of monster constructor?" So, implicitly it would call at the start like a this constructor if I define it. Okay, so that will satisfy our compiler here.
But, I'm actually going to talk a little bit more about this in the next video here. So, I'll example.
But, what I want to just focus on is this here.
Now, you might be wondering, I mean, this is kind of interesting. I have, okay, these attributes here for private, I am able to access them here. I mean, that's that's sort of true that I'm able to do this. But, again, remember these sort of privacy level sort of module level.
Okay? So, I have these, I mean, I can change these attributes and they definitely don't go away, right?
When I sort of have these here.
And let's go ahead and write out what would be monsters at index zero, the power.
Let's actually see if that was actually constructed here.
And the health. Let's go ahead and do that here.
Okay, five and eight. Okay, so it is changing it here.
But, you might be saying again, "Well, this is a little bit strange that I have power and health here. I've marked them private. So, again, if you're coming from other object-oriented languages, you'd say, "Well, you know, those shouldn't be things that should be derived." But, again, remember in D, the visibility level is module level. So, I can see everything uh here. So, usually what we would do is per type um is just go ahead and say, "Hey, let's just go ahead and create a monster.d file. Let's put this in here."
Let's create a dragon.d file.
Uh let's go ahead and put this in here.
And let's go ahead and structure our code just a little bit here.
Uh let me get rid of these comments here.
Let me fold them.
Uh let's see here.
Uh I got to do the set fold method manual for now. There we go.
All right. So, anyways, let's let's make sure we can see all of our code here that we have written.
Um and then in order to use these uh modules here, uh oh, let's actually just uh let's actually just try to compile this and see what errors we get first.
Um I think that's usually more interesting. Uh let's see. So, let's make sure we save everything. Save, save, save.
Okay. So, okay, first things first, undefined identifier monster. So, again, why is that happening? Well, I need to import the monster file here.
Uh so, let's save there.
Uh got a little bit closer. Now, undefined identifier dragon.
Let's bring in the dragon as well. And indeed, you can do these imports uh with commas. I actually like doing that. And I usually do that for things that are in the sort of same family. So, the standard libraries usually end up with one line comma separated. My libraries usually end up another one, and then maybe third-party libraries. Uh so, anyways, just a little note on that there.
Uh okay.
Uh so, we got basically uh a little bit closer here.
Uh and then let's see in our uh, dragon file, well, we need to import monster.
Okay, because that's what it's deriving from.
Uh, okay, now we're getting more interesting error messages, maybe the thing that you would sort of expect here. We are getting no property uh, at line uh, eight here in our main file, where we're saying, "Hey, dot power, there's no property power here for this type." So, um, and again, the same sort of repeated error here, because these are private here. Okay? So, what if I did, let's just go ahead and practice here, protected.
Okay, protected.
Okay, let's try to work our way um, and make this less less encapsulated here.
Uh, still same thing, right? I shouldn't be able to access these outside of the class. These are legal here, it's definitely not complaining about them there, so that's good. Uh, but if I do make these public now, okay, that will work. Okay? So, again, that's just a little bit about how the encapsulation works with the access control. Uh, and you can do the things like maybe you're used to in uh, like C++ something like that. Just make everything public, that also works here. Okay?
Uh, I tend to probably go more this style. I guess it's just a little bit more explicit, although I go back and forth, but anyways, that's something you can do here.
All right, so there you have it. That's how to sort of uh, separate out things here.
Um, and that gives you a basic uh, look here um, of these different uh, types here.
Now, let's keep playing around with this just a little bit more here.
And uh, as I was alluding to in this uh, diagram here, we can also have interfaces. Okay? So, let's go ahead and take a look at how an interface affects this.
Um, and what I think I'm going to do here is just apply it to the monster here. Let's have this interface. Um and let's go ahead and say there's going to be a interface for like breathe fire or something, right? We'll have some lizards, some dragons, and you know, whatever other creatures can breathe fire. And then we want it, you know, do the uh fire attack. You know, something aggressive like that here, okay?
Um so, uh what do I need to do here?
Well, let's say in my class uh for monster, let's say I want to have this uh breathe fire here interface.
Going to compile this and it's going to say, "Okay, hey, uh monster interface function void fire attack is not implemented." So, what do we need to do here? Well, we need to implement the breathe fire attack here.
Breathe fire.
Uh and let's go ahead and do this for all of our monsters, okay?
Um okay. So, again, now our monster uh has implemented fire. We didn't have to do it in dragon. Why? Because dragon is a type of monster, so it's going to inherit that behavior, right? This is by default public function that is inherited here. Now, you might say, "Well, dragons, they breathe a lot of fire. So, um let's go ahead and implement this again."
Uh and what's going to happen here if we try to compile? And you might have seen this error if you're watching all my videos when we did two string. Go ahead and hit enter. Uh we need to explicitly uh override this, okay?
Uh we can't have the same function twice, so we use override there.
And then we'll have the, you know, specific implementation for the dragon here, okay? So, that's one way that we can uh do things here uh with these interfaces.
Now, um I would say it doesn't really make sense for mons all monsters to breathe fire. Um so, let's go ahead and take this off here. And this is where interfaces can be kind of neat. So, we'll have our base sort of monster class here.
Let's get rid of the fire attack.
And then what I'll do here is I want my dragon to be a type of monster. And then D is smart enough that if we pass in the symbol here for the breathe fire here then our dragon will have to implement breathe fire. Let's see what kind of error we get if we leave that override there. I guess it doesn't complain too much here. Let's make sure we saved everything.
That's kind of neat.
Let's see here. So I guess I got to override in the interface or let's just implement it there. Perfect. And then you know, we might have other attributes for our monsters.
Let's have another interface here for flying you know, ability here. Fly.
And let's go ahead and Yeah, dragon should fly.
And undefined identifier here. Let's see a flying, sorry.
Flying, there we go.
And same thing here. So we can have multiple interfaces. So remember multiple interfaces are allowed. Multiple inheritance is not allowed. Only one type here. Okay, so dragons can have as many interfaces that they want. And this is kind of a nice way to code here. So let's go ahead and do our fly.
And then we can see everything here.
Okay, so that's the basic idea here with inheritance and mixing in interfaces which we've just learned about here.
All right, so last little thing that I want to go ahead and show you here. Let's go ahead and let's just work in this little example here towards the bottom here.
And let's go ahead and figure out if I have a monster. I'm just going to call monster M1. I need to use new to create that actual monster and then I do have a constructor here for the health and the power.
And basically what I want to show you how to do it here is how to get the type, okay?
So let's create monster two. This one I'm going to say is a new dragon.
Let's bump up the power a little bit there.
And what if I want to instantiate this as a dragon for this one here?
I'll just call it D1 here and let's just give it a new power or something just to be a little bit random here.
First and foremost, this should work.
Yes, that's good.
But what I want to show you here is the types here.
Type ID of M1 monster one. That's at line number 12 here. And let's just write that out there, okay? Let's repeat this here.
Do the same thing for M2 and for D1 here, okay?
So what I'm showing you here is the run time type information of how the object was created, okay?
At run time, okay? So what are your predictions here when I run this? Okay, it's going to print five and eight from our previous print out, but we should see this M1, M2, and D1. They should take on, you know, the type that they were instantiated at, right? And I can instantiate a monster as a type of dragon here. So I should see probably monster, dragon, dragon here, okay? So let's see if that's true.
I see monster.monster, dragon.dragon, and dragon.dragon here, okay? Perfect.
All right, so hopefully that makes sense when I'm using type ID.
I want to just show you one other thing here.
Um Can I do uh Let's see. Can I do sort of the reverse here? Dragon, let's try dragon seed equals new monster. Uh I don't know, something like that. Is this allowed? Can I go uh, sort of from the, you know, lower type and say, "Hey, create me something lesser." Sort of, you know, upcasting that direction. Yeah, we we can't really do that one, okay? So, just in case you were curious. Uh, illegal. Okay, this is going to give a, uh, error message here.
I mean, we could maybe force cast it or something, um, but yeah, we, you know, we can't, uh, generally go in this, uh, direction here. Okay, so at least statically the type system's going to stop us. All right.
Uh, so I showed you at run time how to figure out, okay, what is the type that we've used new with here.
Okay. Uh, and let me make this a little bit bigger for you. There you are.
Uh, and let's look at the type of, uh, m1 here.
Uh, and I'm going to use string of, which is a property here, and then I'll use write line.
Uh, and if this makes you a little bit uncomfortable, uh, the universal function call, uh, or uniform function call syntax here. Let me write out, uh, this is another way of writing this out, type of d1.stringof.
Uh, you know, these are all doing the same thing here.
Uh, I'll delete that just so you can see.
Uh, and what is this doing here?
Well, type of is telling me the left-hand side, monster, monster, and dragon. So, I do see monster, monster, and dragon here of m1, m2, and d1 respectively. Okay? And this can be, uh, handy, um, on occasion when you're using like is expressions to figure out, is something a type of, you know, uh, monster or dragon. Um, so anyway, I just wanted to show some of those tools so you can kind of have at least, um, this this at least is probably immediately more useful just remembering type ID, which we've used throughout the series.
Um, so so you can see how the object was created, and then you can check, um, in your code, is this a type of dragon? Is this a troll? Is this a You know, figure out what this monster it was instantiated as, for instance, okay?
All right, folks. So, I think I'll go ahead and cut it off there. So, working backwards, the things that we learned, again, we learned about a little bit about introspection here, figuring out the static type, left-hand side of the equation here.
The runtime type, what we've newed the monster as. We've seen that things that are a type of monster can go into the collection here. So, uh by runtime polymorphism, it's a fancy way to say that, right? Um we can and D is doing sort of the bookkeeping for us, but it again allows us to add anything that is a type of monster into this collection. And this is one of the places where, again, inheritance is very helpful, okay? So, you learned about um how to add anything that's in this inheritance hierarchy into common collection, how to figure out the types, and then we've looked at um oops, let's uh runtime polymorphism.
Uh then we looked at uh how to separate out our files into different uh well, our different types, rather, into different files, so that we can respect the public, private, and protected labels.
Um in practice, I often have these in the same file anyways, cuz I don't care as much. I actually like this, but depending on what language you're coming from, you may or may not like this, right? So, you can split things into different files if that uh makes you happier, and that's probably the right thing to do. But, generally speaking, I like because I want my code to be very malleable, uh putting monster and dragon in the same file. But, again, um then you just have to think a little bit about how to enforce, perhaps, these uh public and private specifiers. So, anyways, we learned about that. Public is the default in D for both classes and structs, so just keep that in mind and that things are public to the module which are defined. So, that's why we move these into different files.
Um and then we looked at last thing here, the single inheritance that we can have. So, dragon is a type of monster, but we can have as many interfaces as we want here for any of our class types, whether they're in a hierarchy or not.
Okay, so just reminder on that.
All right, folks. So, we covered quite a bit. I hope you enjoyed this lesson and as always, uh make sure you're following along. We're doing a lot of stuff with classes, so you can check out um courses.mshatto.io and follow along on the D programming language series here or ask questions in the community there or in the comments if you're watching this on YouTube. Um and otherwise, I hope you enjoyed this. We're going to be doing some more uh very, very soon. So, stay tuned for the next episode. Thanks for your time and attention and I'll look forward to uh seeing you in the next one.
Related Videos
Agentforce NOW AMA: Build with React and Salesforce Multi-Framework
SalesforceDevs
490 views•2026-05-28
How agent o11y differs from traditional o11y — Phil Hetzel, Braintrust
aiDotEngineer
450 views•2026-05-28
Re: 🗣️📍theprophedu📍2026 GST 103 CLASS (E-EXAM REVISION)
theprophedu
636 views•2026-06-04
WEB TECHNOLOGIES UNIT-2 | Degree 4th sem BCOM Computers web technologies unit-2 full explanation💯✅
LearnwithSahera
1K views•2026-05-29
More tests are always better? How to use AI to identify tests that bring little value
Alliance4Qualification
335 views•2026-05-29
Search Algorithms Explained in 60 Seconds! 🤖💨
samarthtuliofficial
218 views•2026-06-01
People of Game of Thrones using JavaScript DOM
AltCampus
296 views•2026-05-30
Introduction to Problem Solving Part - 1 | Lecture 1 | Intermediate DSA
ascensionix
107 views•2026-05-29











