digitalmars.D.learn - Alternative to friend functions?
- Adnan (43/43) Feb 18 2020 What is the alternative to C++'s friend functions in D?
- Petar Kirov [ZombineDev] (8/51) Feb 18 2020 In D the unit of encapsulation is not class, but module, and so
- Simen =?UTF-8?B?S2rDpnLDpXM=?= (39/49) Feb 18 2020 Petar's answer covers your question, so I won't elaborate on
- Bienlein (6/49) Feb 20 2020 I would make Husband and Wife subclasses of a common abstract
- ShadoLight (22/83) Feb 20 2020 But where in that inheritance hierarchy will you slot the Spouse
What is the alternative to C++'s friend functions in D? module stable_matching; alias FemaleID = int; alias MaleID = int; class Person { string name; int id; } class Male : Person { this(string name = "Unnamed Male") { static int nextID = 0; this.id = nextID++; this.name = name; } } class Female : Person { this(string name = "Unnamed Female") { static int nextID = 0; this.id = nextID++; this.name = name; } } class Husband(uint N) : Male { FemaleID engagedTo = -1; const FemaleID[N] preferences; this(FemaleID[N] preferences) { this.preferences = preferences; } } class Wife(uint N) : Female { FemaleID engagedTo = -1; const MaleID[N] preferences; this(MaleID[N] preferences) { this.preferences = preferences; } } void engage(N)(ref Wife!N, wife, ref Husband!N husband) { // Here, I want to access both husband and wife's engaged_to } class MatchPool(uint N) { Husband!N[N] husbands; Wife!N[N] wives; }
Feb 18 2020
On Tuesday, 18 February 2020 at 12:43:22 UTC, Adnan wrote:What is the alternative to C++'s friend functions in D? module stable_matching; alias FemaleID = int; alias MaleID = int; class Person { string name; int id; } class Male : Person { this(string name = "Unnamed Male") { static int nextID = 0; this.id = nextID++; this.name = name; } } class Female : Person { this(string name = "Unnamed Female") { static int nextID = 0; this.id = nextID++; this.name = name; } } class Husband(uint N) : Male { FemaleID engagedTo = -1; const FemaleID[N] preferences; this(FemaleID[N] preferences) { this.preferences = preferences; } } class Wife(uint N) : Female { FemaleID engagedTo = -1; const MaleID[N] preferences; this(MaleID[N] preferences) { this.preferences = preferences; } } void engage(N)(ref Wife!N, wife, ref Husband!N husband) { // Here, I want to access both husband and wife's engaged_to } class MatchPool(uint N) { Husband!N[N] husbands; Wife!N[N] wives; }In D the unit of encapsulation is not class, but module, and so `private` only restricts access from other modules. If `engage` is declared in the same module as the classes, you should have no problems accessing their private members. If you want to put `engage` in a different module, than you can use the `package` access modifier to allow all modules in a given package to access `package` members.
Feb 18 2020
On Tuesday, 18 February 2020 at 12:43:22 UTC, Adnan wrote:class Wife(uint N) : Female { FemaleID engagedTo = -1; const MaleID[N] preferences; this(MaleID[N] preferences) { this.preferences = preferences; } } void engage(N)(ref Wife!N, wife, ref Husband!N husband) { // Here, I want to access both husband and wife's engaged_to }Petar's answer covers your question, so I won't elaborate on that, but I'd like to point out that as Wife and Husband are classes, you probably don't intend to take them by ref - classes are always by ref in D, so you're effectively passing a reference to a reference to a class in `engage`. Basically: class Foo { int n; } void fun(Foo f) { f.n = 3; // Local copy of the reference - does not modify other references. f = null; } void gun(ref Foo f) { f = null; } unittest { Foo f = new Foo(); Foo g = f; f.n = 17; // f and g point to the same object: assert(f.n == 17); assert(g.n == 17); fun(f); // fun() changed the object that both f and g point to: assert(f.n == 3); assert(g.n == 3); gun(f); // gun() changed f to no longer point at the same object, but left g untouched: assert(f is null); assert(g !is null); assert(g.n == 3); } -- Simen
Feb 18 2020
On Tuesday, 18 February 2020 at 12:43:22 UTC, Adnan wrote:What is the alternative to C++'s friend functions in D? module stable_matching; alias FemaleID = int; alias MaleID = int; class Person { string name; int id; } class Male : Person { this(string name = "Unnamed Male") { static int nextID = 0; this.id = nextID++; this.name = name; } } class Female : Person { this(string name = "Unnamed Female") { static int nextID = 0; this.id = nextID++; this.name = name; } } class Husband(uint N) : Male { FemaleID engagedTo = -1; const FemaleID[N] preferences; this(FemaleID[N] preferences) { this.preferences = preferences; } } class Wife(uint N) : Female { FemaleID engagedTo = -1; const MaleID[N] preferences; this(MaleID[N] preferences) { this.preferences = preferences; } } void engage(N)(ref Wife!N, wife, ref Husband!N husband) { // Here, I want to access both husband and wife's engaged_to } class MatchPool(uint N) { Husband!N[N] husbands; Wife!N[N] wives; }I would make Husband and Wife subclasses of a common abstract superclass Spouse that declares the engagedTo var. The Spouse superclass would also be the place where to put the engage method. What is different for males and females you can redefine in the respective subclass.
Feb 20 2020
On Thursday, 20 February 2020 at 08:02:48 UTC, Bienlein wrote:On Tuesday, 18 February 2020 at 12:43:22 UTC, Adnan wrote:But where in that inheritance hierarchy will you slot the Spouse class in? You don't have multiple inheritance in D, so are you thinking along these lines?: class Person {..} class Spouse : Person {..} class Male : Spouse {..} class Female : Spouse {..} That implies every Male and Female 'is a' Spouse which, feels a bit clunky to me. Maybe a better design for your idea is to make Spouse an interface; something along these lines: class Person {..} interface Spouse {void engage(..);} class Male : Person, Spouse {..} class Female : Person, Spouse {..} Then, as you say, the respective engage(..) implementations are done in the Male/Female subclass. Maybe you can even declare a winArgument(..) method returning a bool in the Spouse interface. For the Male class the implementation will be real easy: just return false! [Disclaimer]: Last paragraph not to be taken seriously!What is the alternative to C++'s friend functions in D? module stable_matching; alias FemaleID = int; alias MaleID = int; class Person { string name; int id; } class Male : Person { this(string name = "Unnamed Male") { static int nextID = 0; this.id = nextID++; this.name = name; } } class Female : Person { this(string name = "Unnamed Female") { static int nextID = 0; this.id = nextID++; this.name = name; } } class Husband(uint N) : Male { FemaleID engagedTo = -1; const FemaleID[N] preferences; this(FemaleID[N] preferences) { this.preferences = preferences; } } class Wife(uint N) : Female { FemaleID engagedTo = -1; const MaleID[N] preferences; this(MaleID[N] preferences) { this.preferences = preferences; } } void engage(N)(ref Wife!N, wife, ref Husband!N husband) { // Here, I want to access both husband and wife's engaged_to } class MatchPool(uint N) { Husband!N[N] husbands; Wife!N[N] wives; }I would make Husband and Wife subclasses of a common abstract superclass Spouse that declares the engagedTo var. The Spouse superclass would also be the place where to put the engage method. What is different for males and females you can redefine in the respective subclass.
Feb 20 2020