www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Nested Classes with inheritance

reply Salih Dincer <salihdb hotmail.com> writes:
Greetings to all...

There are nested classes as below. But beware, there's also 
inheritance, extra! If you construct ```Bar b``` from main(), 
it's okay. But if declare the constructor in Foo(), the program 
crashes with a segmentation error.

Is this not legal? Like two mirrors are facing each other, that I 
do?

```d
class Foo
{
     Bar b;
     int i;

     this(int n)
     {
         this.i = n;
         //this.b = new Bar(this.i); // compiles but crashes
     }

     class Bar : Foo
     {
         int i;

         this(int n)
         {
             this.i = n;
             super(this.i);
         }

     }
}

void main()
{
     auto foo = new Foo(1);
     auto bar = foo.new Bar(1);
     foo.b = bar;

     assert(foo.i == foo.b.i);
}
```
SDB 79
Mar 18 2022
parent reply user1234 <user1234 12.de> writes:
On Saturday, 19 March 2022 at 00:05:54 UTC, Salih Dincer wrote:
 Greetings to all...

 There are nested classes as below. But beware, there's also 
 inheritance, extra! If you construct ```Bar b``` from main(), 
 it's okay. But if declare the constructor in Foo(), the program 
 crashes with a segmentation error.

 Is this not legal? Like two mirrors are facing each other, that 
 I do?

 ```d
 class Foo
 {
     Bar b;
     int i;

     this(int n)
     {
         this.i = n;
         //this.b = new Bar(this.i); // compiles but crashes
     }

     class Bar : Foo
     {
         int i;

         this(int n)
         {
             this.i = n;
             super(this.i);
         }

     }
 }

 void main()
 {
     auto foo = new Foo(1);
     auto bar = foo.new Bar(1);
     foo.b = bar;

     assert(foo.i == foo.b.i);
 }
 ```
 SDB 79
That crashes because of the creation of `Bar b` member, which itself has a Bar b member, which itself... One solution is to create the member depending on some condition, example: ```d if (typeid(this) !is typeid(Bar)) this.b = new Bar(this.i); ```
Mar 18 2022
next sibling parent reply Era Scarecrow <rtcvb32 yahoo.com> writes:
On Saturday, 19 March 2022 at 00:16:48 UTC, user1234 wrote:
 That crashes because of the creation of `Bar b` member, which 
 itself has a Bar b member, which itself...
Mhmm... So There's Foo with Bar b, which has Bar b which has Bar b which... just keeps going over and over again. It appears to me that it only crashes when you fully run out of memory then. Much like a function calling itself and you exhaust all your stack space. I'd suggest avoiding self-inheritance. No one wants to be their own Grandpa
Mar 18 2022
parent reply user1234 <user1234 12.de> writes:
On Saturday, 19 March 2022 at 05:25:01 UTC, Era Scarecrow wrote:
 On Saturday, 19 March 2022 at 00:16:48 UTC, user1234 wrote:
 That crashes because of the creation of `Bar b` member, which 
 itself has a Bar b member, which itself...
Mhmm... So There's Foo with Bar b, which has Bar b which has Bar b which... just keeps going over and over again. It appears to me that it only crashes when you fully run out of memory then. Much like a function calling itself and you exhaust all your stack space. I'd suggest avoiding self-inheritance. No one wants to be their own Grandpa
I think OP is learning OOP. His error looks like that for the least.
Mar 19 2022
parent reply Era Scarecrow <rtcvb32 yahoo.com> writes:
On Saturday, 19 March 2022 at 12:23:02 UTC, user1234 wrote:
 I think OP is learning OOP. His error looks like that for the 
 least.
True. Looking at the code it shouldn't spaghetti in on itself infinitely and is basically clean in his intent. Inheritance and Polymorphism is one of the hardest things to grasp mostly because examples they give in other books of 'objects' is so far unrelated to software that it doesn't really compare. `"An object is like a book which you can read and turn the page..."` but then can't tear or burn or hand to a friend or put on the shelf upside down, or put your coffee on top of while you surf on the web leaving a ring on the book. Or comparing inheritance and polymorphism to animals but other than overriding the output function to 'meow' or something doesn't really help, while comparing to say a bank account management or something would be much better. Maybe I'm just venting on the C++ Primer from 1997 that just annoyed me to hell.
Mar 19 2022
parent reply Salih Dincer <salihdb hotmail.com> writes:
On Sunday, 20 March 2022 at 01:28:44 UTC, Era Scarecrow wrote:
 Inheritance and Polymorphism is one of the hardest things to 
 grasp mostly because examples they give in other books of 
 'objects' is so far unrelated to software that it doesn't 
 really compare. `"An object is like a book which you can read 
 and turn the page..."` but then can't tear or burn or hand to a 
 friend or put on the shelf upside down, or put your coffee on 
 top of while you surf on the web leaving a ring on the book.
You are right, difficult model yet so abeyant. Moreover, there is a lot of freedom given in D. I think OOP alone is not worth 5 cents without design patterns. For example, my codes I just wrote below is nonsense. It looks like a sailboat trying to navigate a windless ocean: ```d class Year { int num; this(int year) { this.num = year; } auto opBinary(string op)(Year rhs) if(op == "-") { // Negative & Option 1a return new Year(this.num - rhs.num); } auto opBinary(string op)(int rhs) if(op == "-") { // Negative & Option 2a return new Year(this.num - rhs); } auto opBinary(string op)(Year rhs) if(op == "+") { // Positive & Option 1b this.num += rhs.num; return this; } auto opBinary(string op)(int rhs) if(op == "+") { // Positive & Option 2b this.num += rhs; return this; } override string toString() const { import std.conv; return num.to!string; } } void naim() { import std.stdio; enum categoryID : ubyte { leader, champion } class Person : Year { string name; int born, age; categoryID cat; bool life; this(string name, int[] years, int cat) { super(years[1]); this.name = name; this.born = years[0]; this.age = isDeath(); this.cat = cast(categoryID)cat; } int isDeath() { return life ? super.num - born: 2022 - born; } } auto years = [ 1967, 2017 ]; auto NaimS = new Person ( "Naim Süleymanoğlu", years, 1 ); with(NaimS) { life = true; writefln("%s\n(Born %d, when he died, was %d)", name , born , isDeath); } } version = 1; void main() { version(1) { auto birth = new Year(1881); auto death = new Year(1938); auto print = death - birth; import core.stdc.stdio; printf("Atatürk was %d", print.num); printf(" years old when he died:("); } else naim(); } ``` OOP can be aggressive like a dog. I think D should be a little more rigid on OOP. SDB 79
Mar 19 2022
parent Era Scarecrow <rtcvb32 yahoo.com> writes:
On Sunday, 20 March 2022 at 05:44:44 UTC, Salih Dincer wrote:
 On Sunday, 20 March 2022 at 01:28:44 UTC, Era Scarecrow wrote:
 Inheritance and Polymorphism is one of the hardest things to 
 grasp mostly because examples they give in other books of 
 'objects' is so far unrelated to software that it doesn't 
 really compare.
You are right, difficult model yet so abeyant. Moreover, there is a lot of freedom given in D. I think OOP alone is not worth 5 cents without design patterns. OOP can be aggressive like a dog. I think D should be a little more rigid on OOP.
Actually one good example for Objects is a game, specifically Magic The Gathering. MTG is a card game, of that everyone knows. But there's so many effects. When it comes into play, when it goes to the graveyard, if it gets exiled, cost to cast it from the gaveyard/exile, tapping, untapping, paying and tapping to do an ability, milling cards, drawing cards, scrying cards, attacking without untapping, deathtouch, islandwalk. Then there's enchantments, equipment, passive always active abilities (*all your creatures get +0/+1*) and a myriad of other things. Now with that out of the way making a base 'card' with all it's actions as a mere interface and then making each card individually OR inheriting from a base card using polymorphism would be a great way to do things. Going the one route ```d abstract class Card { string name, description, picture, quote; string types; //Green Insect Token, Indestructable, etc int basePower, baseToughness; Card[] enchantments; //affecting this card specifically static Card[] globalEnchantments, //affecting all cards playerEnchantments; //affecting only my own cards //When a card leaves play remove from enchantments list. //globals will just remove from the static list void purgeCard(Card target); //calculate power int power() { int t; foreach(x; enchantments) {t += x.basePower;} foreach(x; globalEnchantments) {t += x.basePower;} foreach(x; playerEnchantments) {t += x.basePower;} return t; } int toughness(); //etc for a base class with expected functional hooks for combat, instants etc. } class Wurm : Card { this() { name = "Greater Wurm"; quote = "When the Wurm comes, all flee it's destruction"; basePower = 3; baseToughness = 3; } //no tap or other abilities, left blank } class Beetle : Card { Card original; this(Card target) { description = "The target card becomes a 0/1 indestructible beetle"; types="Green,Insect,Indestructible,Enchantment"; //code to swap original and target } ~this() { //unswap } override int power(){return 0;} override int toughness(){return 1;} } class Sword : Card { this() { name="Soldier's sword"; description = "Enchanted creature gets +2/0"; types="Enchantment,Equipment,Colorless"; basePower = 2; } this(Card target) { target.enchantments ~= this; } } ``` Here you have a base card to work with, a monster, enchantment and an override.
Mar 20 2022
prev sibling parent Salih Dincer <salihdb hotmail.com> writes:
On Saturday, 19 March 2022 at 00:16:48 UTC, user1234 wrote:
 ```d
 if (typeid(this) !is typeid(Bar))
     this.b = new Bar(this.i);
 ```
A very clever and ingenious solution. Thanks... SDB 79
Mar 19 2022