December 27, 2022
On Sunday, 25 December 2022 at 15:29:40 UTC, Timon Gehr wrote:
> I don't think it's about saving the typing, it's about not allowing bugs to appear because people _forgot_ to type.

This is exactly true... and it brings to mind an alternate idea: require a non-abstract method must be overridden in a child class.

Consider this:

class Dupable {
    __mustOverride("hint message") Dupable dup() { return new Dupable(); }
}

class Child : Dupable {
   // if you forgot to override dup, you'd get the wrong type out
   // but since the parent had mustoverride, the compiler will tell us
}


error: class Child must override method `Dupable dup`
hint: hint message


Then it prods them in the right direction and the hint message can tell them to mixin something.

Destroy.
December 28, 2022

On Tuesday, 27 December 2022 at 01:15:42 UTC, Adam D Ruppe wrote:

>

On Sunday, 25 December 2022 at 15:29:40 UTC, Timon Gehr wrote:

>

I don't think it's about saving the typing, it's about not allowing bugs to appear because people forgot to type.

This is exactly true... and it brings to mind an alternate idea: require a non-abstract method must be overridden in a child class.

Consider this:

class Dupable {
__mustOverride("hint message") Dupable dup() { return new Dupable(); }
}

class Child : Dupable {
// if you forgot to override dup, you'd get the wrong type out
// but since the parent had mustoverride, the compiler will tell us
}

error: class Child must override method Dupable dup
hint: hint message

Then it prods them in the right direction and the hint message can tell them to mixin something.

Destroy.

While this works, there is a small blurring. We want to express that a specific mixin template is mixed into the sub class, but what we actually say is, that a specific method needs to be overridden. Therefore the developer can just override the method without actual mixin the mixin template.

From my point of view, it would be neat if I could express that a specific mixin template should be evaluated within each child class. In the sample below the syntax class mixin Foo; is used.

import std;

mixin template Foo()
{
    void fancyMethod(){
        writeln(__traits(identifier, typeof(this)));
    }
}

class Animal {
    class mixin Foo;
}

class Dog : Animal {}
class Bulldog : Dog {}

void main() {
   new Animal().fancyMethod();
   new Dog().fancyMethod();
   new Bulldog().fancyMethod();
}

Kind regards
Andre

December 28, 2022

On Sunday, 25 December 2022 at 11:07:30 UTC, Andre Pany wrote:

>

Hi,

Since a few days I think about a new concept called Mixin Methods.
I wonder whether it makes sense to write a DIP or I maybe miss an obvious issue with the concept?

Mixin Methods serves the purpose to enable introspection in class based frameworks by inheritance.

If you look at frameworks like d-unit (https://github.com/linkrope/dunit/blob/master/example.d) or arsd.jni (https://arsd-official.dpldocs.info/arsd.jni.html) they try to solve the issues in different ways.
In d-unit the unit test classes do not have inheritance but each unit test class needs to add a mixin statement mixin UnitTest;.

In arsd.jni there is another concept, the classes inherits introspection by inheriting from the root class and the current class as template parameter:

final class Hello : JavaClass!("", Hello) {
}

The issue with this concept is, all classes inherits from the root class (JavaClass) directly. Inheritance from another child class (e.g. Hello) is not possible.

The concept Mixin Methods can be used like this

import std;
void main()
{
   new Animal().fancyMethod();
   new Dog().fancyMethod();
   new Bulldog().fancyMethod();
}

class Animal {

    mixin void fancyMethod(){
        writeln(__traits(identifier, typeof(this)));
    }

}

class Dog : Animal {}

class Bulldog : Dog {}

Due to the mixin statement, the compiler will copy the fancyMethod into all sub classes of class Animal as method overload.

class Dog : Animal {
// compiler
override void fancyMethod(){
writeln(__traits(identifier, typeof(this)));
}
// compiler
}

class Bulldog : Dog {
// compiler
override void fancyMethod(){
writeln(__traits(identifier, typeof(this)));
}
// compiler
}

As you can see, Mixin Methods works for non static and non final methods. The benefit is, the users just need to inherit from a framework class to inherit the introspection capabilities.

Does it make sense to create here a DIP or do you see any road blocker?

Kind regards
Andre

We have the template this parameter that would on the surface work like this feature:

import std;
void main()
{
   new Animal().fancyMethod();
   new Dog().fancyMethod();
   new Bulldog().fancyMethod();
}

class Animal {

    void fancyMethod(this This)(){
        writeln(__traits(identifier, This));
    }

}

class Dog : Animal {}

class Bulldog : Dog {}

outputs

Animal
Dog
Bulldog

overriding works by redeclaring the method inside the sub-classes.

However the problem with this is that the methods are just templates, e.g. they work like UFCS functions, only knowing the type they are being called on and not the actual type. If you cast your Bulldog to Animal, you will call fancyMethod with Animal as template parameter here. (breaking a bunch of OOP patterns and the advantages of using inheritance)

I think some mixin-into-subclasses approach would be quite nice for a lot of things, but I think it's better if the user needs to explicitly mixin extra methods, so that they don't magically appear. (+ explicit mixin can specify extra options)

Having some way to require users to mixin something would be something worth looking into though I think. With methods you can, at least for types directly inheriting from the abstract class, rely on linker errors. This doesn't scale well though, as it will introduce runtime bugs once inheriting from other classes that have implementations.

1 2
Next ›   Last »