Thread overview
Interface/abstract constructors
May 16, 2011
useo
May 16, 2011
Timon Gehr
May 16, 2011
Jonathan M Davis
May 16, 2011
nrgyzer
May 16, 2011
nrgyzer
May 16, 2011
Hey guys,

is there any chance to create an abstract constructor like:

abstract class ABC {

   abstract this();

}

DMD always says "...this non-virtual functions cannot be abstract" - when I use an interface like:

interface ABC {

   this();

}

I get a similar error: "...constructors, destructors, postblits, invariants, unittests, new and delete functions are not allowed in interface ABC"

Is there any solution or is it possible to create such inheritances in DMD?
May 16, 2011
> Hey guys,
>
> is there any chance to create an abstract constructor like:
>
> abstract class ABC {
>
>    abstract this();
>
> }
>
> DMD always says "...this non-virtual functions cannot be abstract" - when I use an interface like:
>
> interface ABC {
>
>    this();
>
> }
>
> I get a similar error: "...constructors, destructors, postblits, invariants, unittests, new and delete functions are not allowed in interface ABC"
>
> Is there any solution or is it possible to create such inheritances in DMD?

How about:
abstract class ABC{
    this();
}

Timon
May 16, 2011
On 2011-05-16 12:32, useo wrote:
> Hey guys,
> 
> is there any chance to create an abstract constructor like:
> 
> abstract class ABC {
> 
>    abstract this();
> 
> }
> 
> DMD always says "...this non-virtual functions cannot be abstract" - when I use an interface like:
> 
> interface ABC {
> 
>    this();
> 
> }
> 
> I get a similar error: "...constructors, destructors, postblits, invariants, unittests, new and delete functions are not allowed in interface ABC"
> 
> Is there any solution or is it possible to create such inheritances in DMD?

An abstract constructor makes no sense. It also makes no sense for an interface to have a constructor. A constructor is specific to the class that it's on. It is not virtual at all and has nothing to do with the inheritance hierarchy beyond the fact that subclasses can and will call the constructors of base classes in their own constructors.

- Jonathan M Davis
May 16, 2011
On Mon, 16 May 2011 15:32:43 -0400, useo <unknown@unknown.com> wrote:

> Hey guys,
>
> is there any chance to create an abstract constructor like:
>
> abstract class ABC {
>
>    abstract this();
>
> }
>
> DMD always says "...this non-virtual functions cannot be abstract" -
> when I use an interface like:
>
> interface ABC {
>
>    this();
>
> }
>
> I get a similar error: "...constructors, destructors, postblits,
> invariants, unittests, new and delete functions are not allowed in
> interface ABC"
>
> Is there any solution or is it possible to create such inheritances
> in DMD?

I think what you are trying to do is say, "if a class implements interface ABC, it must have a default constructor".  Such a requirement is faulty.  The point of an interface is to able to pass a portion of a class' functionality to a function during runtime.  However, the instance must *already exist*.  It makes no sense to posit requirements on the constructor.

What you want is a compile-time requirement using a template constraint.  You may think "damn, but I don't want to make my function a template", I'd say see previous point ;)

-Steve
May 16, 2011
== Auszug aus Steven Schveighoffer (schveiguy@yahoo.com)'s Artikel
> On Mon, 16 May 2011 15:32:43 -0400, useo <unknown@unknown.com>
wrote:
> > Hey guys,
> >
> > is there any chance to create an abstract constructor like:
> >
> > abstract class ABC {
> >
> >    abstract this();
> >
> > }
> >
> > DMD always says "...this non-virtual functions cannot be
abstract" -
> > when I use an interface like:
> >
> > interface ABC {
> >
> >    this();
> >
> > }
> >
> > I get a similar error: "...constructors, destructors, postblits, invariants, unittests, new and delete functions are not allowed in interface ABC"
> >
> > Is there any solution or is it possible to create such
inheritances
> > in DMD?
> I think what you are trying to do is say, "if a class implements
interface
> ABC, it must have a default constructor".  Such a requirement is
faulty.
> The point of an interface is to able to pass a portion of a class' functionality to a function during runtime.  However, the instance
must
> *already exist*.  It makes no sense to posit requirements on the
> constructor.
> What you want is a compile-time requirement using a template
constraint.
> You may think "damn, but I don't want to make my function a
template", I'd
> say see previous point ;)
> -Steve

Okay, thanks... perhaps someone know a better solution: I have one big file which contains some other files (let's say: blocks). Each block has it's own signature... by reading the big file, I read the signature of each block. Based on the signature, I read block A, block B or another Block. To do that, I want call the block-specific constructor which reads the next bytes.

!Semicode:

...
ABC[] blocks;
...
while (!eof(bigfile)) {
  read(signature);
  if (signature==A) blocks ~= new A(bigfile);
  else if (signature==B) blocks ~= new B(bigfile);
  ...
}
...
May 16, 2011
On Mon, 16 May 2011 16:12:05 -0400, nrgyzer <nrgyzer@gmail.com> wrote:

> == Auszug aus Steven Schveighoffer (schveiguy@yahoo.com)'s Artikel
>> On Mon, 16 May 2011 15:32:43 -0400, useo <unknown@unknown.com>
> wrote:
>> > Hey guys,
>> >
>> > is there any chance to create an abstract constructor like:
>> >
>> > abstract class ABC {
>> >
>> >    abstract this();
>> >
>> > }
>> >
>> > DMD always says "...this non-virtual functions cannot be
> abstract" -
>> > when I use an interface like:
>> >
>> > interface ABC {
>> >
>> >    this();
>> >
>> > }
>> >
>> > I get a similar error: "...constructors, destructors, postblits,
>> > invariants, unittests, new and delete functions are not allowed in
>> > interface ABC"
>> >
>> > Is there any solution or is it possible to create such
> inheritances
>> > in DMD?
>> I think what you are trying to do is say, "if a class implements
> interface
>> ABC, it must have a default constructor".  Such a requirement is
> faulty.
>> The point of an interface is to able to pass a portion of a class'
>> functionality to a function during runtime.  However, the instance
> must
>> *already exist*.  It makes no sense to posit requirements on the
>> constructor.
>> What you want is a compile-time requirement using a template
> constraint.
>> You may think "damn, but I don't want to make my function a
> template", I'd
>> say see previous point ;)
>> -Steve
>
> Okay, thanks... perhaps someone know a better solution: I have one
> big file which contains some other files (let's say: blocks). Each
> block has it's own signature... by reading the big file, I read the
> signature of each block. Based on the signature, I read block A,
> block B or another Block. To do that, I want call the block-specific
> constructor which reads the next bytes.
>
> !Semicode:
>
> ...
> ABC[] blocks;
> ...
> while (!eof(bigfile)) {
>   read(signature);
>   if (signature==A) blocks ~= new A(bigfile);
>   else if (signature==B) blocks ~= new B(bigfile);
>   ...
> }
> ...

No special requirements are necessary.  How would this compile if A or B did not have a bigfile constructor?  The interface specification is not needed.

If D supported runtime reflection (and it does to a very very small degree), then you could use it to ensure the correct constructor is available.

-Steve
May 16, 2011
== Auszug aus Steven Schveighoffer (schveiguy@yahoo.com)'s Artikel
> On Mon, 16 May 2011 16:12:05 -0400, nrgyzer <nrgyzer@gmail.com>
wrote:
> > == Auszug aus Steven Schveighoffer (schveiguy@yahoo.com)'s Artikel
> >> On Mon, 16 May 2011 15:32:43 -0400, useo <unknown@unknown.com>
> > wrote:
> >> > Hey guys,
> >> >
> >> > is there any chance to create an abstract constructor like:
> >> >
> >> > abstract class ABC {
> >> >
> >> >    abstract this();
> >> >
> >> > }
> >> >
> >> > DMD always says "...this non-virtual functions cannot be
> > abstract" -
> >> > when I use an interface like:
> >> >
> >> > interface ABC {
> >> >
> >> >    this();
> >> >
> >> > }
> >> >
> >> > I get a similar error: "...constructors, destructors,
postblits,
> >> > invariants, unittests, new and delete functions are not
allowed in
> >> > interface ABC"
> >> >
> >> > Is there any solution or is it possible to create such
> > inheritances
> >> > in DMD?
> >> I think what you are trying to do is say, "if a class implements
> > interface
> >> ABC, it must have a default constructor".  Such a requirement is
> > faulty.
> >> The point of an interface is to able to pass a portion of a
class'
> >> functionality to a function during runtime.  However, the
instance
> > must
> >> *already exist*.  It makes no sense to posit requirements on the
> >> constructor.
> >> What you want is a compile-time requirement using a template
> > constraint.
> >> You may think "damn, but I don't want to make my function a
> > template", I'd
> >> say see previous point ;)
> >> -Steve
> >
> > Okay, thanks... perhaps someone know a better solution: I have one big file which contains some other files (let's say: blocks). Each block has it's own signature... by reading the big file, I read
the
> > signature of each block. Based on the signature, I read block A, block B or another Block. To do that, I want call the block-
specific
> > constructor which reads the next bytes.
> >
> > !Semicode:
> >
> > ...
> > ABC[] blocks;
> > ...
> > while (!eof(bigfile)) {
> >   read(signature);
> >   if (signature==A) blocks ~= new A(bigfile);
> >   else if (signature==B) blocks ~= new B(bigfile);
> >   ...
> > }
> > ...
> No special requirements are necessary.  How would this compile if A
or B
> did not have a bigfile constructor?  The interface specification is
not
> needed.
> If D supported runtime reflection (and it does to a very very small
> degree), then you could use it to ensure the correct constructor is
> available.
> -Steve

It's semicode, so I haven't try to implement it... it should only
show what I'm trying to do.
I'm currently thinking about an empty constructor in an abstract
class like:

abstract class ABC {
   this(Stream) {
      // do nothing
   }
}

class A : ABC {

   this(Stream s) {
      super(s);
      // read my block-specific bytes
   }

}
May 16, 2011
On Mon, 16 May 2011 16:34:20 -0400, nrgyzer <nrgyzer@gmail.com> wrote:

> == Auszug aus Steven Schveighoffer (schveiguy@yahoo.com)'s Artikel

>> If D supported runtime reflection (and it does to a very very small
>> degree), then you could use it to ensure the correct constructor is
>> available.
>> -Steve
>
> It's semicode, so I haven't try to implement it... it should only
> show what I'm trying to do.
> I'm currently thinking about an empty constructor in an abstract
> class like:
>
> abstract class ABC {
>    this(Stream) {
>       // do nothing
>    }
> }
>
> class A : ABC {
>
>    this(Stream s) {
>       super(s);
>       // read my block-specific bytes
>    }
>
> }

First, this should work.  Second, there is no good reason to do this.  An abstract class is allowed to have an empty constructor, but does not force one to implement a Stream-accepting constructor.

For example, this would be a valid subclass:

class A : ABC {
   this() { super(null); }
}

I'm not very good at explaining things sometimes, but if you think about this for a while, it should sink in.  Construction is a concrete activity, you need to have all information about a class to construct it.  Interfaces and polymorphism is an abstract activity, you do not need to have the full definition of the class to call virtual methods.

There is no point to have a constructor definition to force a signature, because it just won't matter.  The derived class does not have to override base constructors because base constructors are not virtual methods.

What you probably want is a factory method such as:

ABC abcfactory(Stream s)
{
   header = readHeader(s);
   if(header == Aheader)
      return new A(s);
   ...
   else
      throw new Exception("Unknown header");
}

What you should put in ABC is methods you would call on the objects *after* they are constructed.

Now, with runtime reflection, you can "look up" classes based on the class names and their appropriate constructors.  I've written such systems in C#, and it's not extremely easy to do it safely.  It's much more straightforward and less error prone to just use a factory method like the above.

-Steve