Thread overview
Nested Classes with inheritance
Mar 19, 2022
Salih Dincer
Mar 19, 2022
user1234
Mar 19, 2022
Era Scarecrow
Mar 19, 2022
user1234
Mar 20, 2022
Era Scarecrow
Mar 20, 2022
Salih Dincer
Mar 20, 2022
Era Scarecrow
Mar 19, 2022
Salih Dincer
March 19, 2022

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?

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

March 19, 2022

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?

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:

if (typeid(this) !is typeid(Bar))
    this.b = new Bar(this.i);
March 19, 2022

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

March 19, 2022

On Saturday, 19 March 2022 at 00:16:48 UTC, user1234 wrote:

>
if (typeid(this) !is typeid(Bar))
    this.b = new Bar(this.i);

A very clever and ingenious solution. Thanks...

SDB@79

March 19, 2022

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.

March 20, 2022

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.

March 20, 2022

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:

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

March 20, 2022

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

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.