This class type

That may have been discussed before, but I did not find the right search terms for it. In strongly typed object-oriented languages like C++ or Java, how do you designate the type of the class in class methods?
A typical use would be the return type of factory methods but it would be useful elsewhere too. Eg.

MyClass MyClass::newInstance();

The problem with the code above is that in a derived class, the signature allows newInstance to return an instance of the base class-- the signature is not restrictive enough.

class MySubClass: MyClass
...
MyClass MySubClass::newInstance(); // WRONG newInstance must return MySubClass

There should be some way to tell the compiler that the type returned is that of the class it is invoked on, is there? Or is there simply a covalence rule for return types such that you would write

MySubClass MySubClass::newInstance();

...which looks a bit hackish to me. The signature needs to be written again for each subclass. And it needs to be extended to parameters too for eg. clone

int MyClass::clone(MyClass obj1, MyClass& obj2);

What I am looking for is something like:

ThisClassType MyClass::newInstance();

Any insight is welcome.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

MyType, ThisType, SelfType, ThisClass, etc

The concept comes with various names. Here's a paper on a typed polymorphic lambda calculus encoding: An Object Encoding For SelfType.

Here's a paper on extending Java with it: LOOJ: Weaving LOOM into Java.

Nice, thanks for the links.

Nice, thanks for the links. Seems to be referred to as the binary method problem, where two parameters are of same type. As there does not seem to be an accepted convention for it I will need to come with my own (and look hard on whether I need exact types)

If the binary method problem

If the binary method problem is what you're looking into, Pierce's book "Types and Programming Languages" covers this. For public info, you can start with Pierce and Cardelli's On Binary Methods.

On Binary Methods

That is interesting as well.

In my case, I was looking at class methods rather than instance methods. On the other hand in the paper we have

class PointClass 
  instance variables 
    xValue: real 
    yValue: real 
  methods 
    x: real is return(xValue)
    y: real is return(yValue)
    equal(p: Point): bool is 
       return( (xValue==p.x) && (yValue==p.y) ) 
end class 

class ColorPointClass subclass of PointClass
  instance variables 
    -- xValue and yValue are inherited
    cValue: string
  methods 
    -- x and y are inherited
    c: string is return(cValue)
    -- equal is overriden
    equal(p: ColorPoint): bool is 
        return( (cValue==p.c) && (xValue==p.x) && (yValue==p.y) ) 
end class

If I make equal a class method it will look like

-- class PointClass
  class methods
    equal(p1, p2: Point): bool is 
       return( (p1.xValue==p2.xValue) && (p1.yValue==p2.yValue) )  

-- class ColorPointClass
  class methods
    -- equal is overriden
    equal(cp1, cp2: ColorPoint): bool is 
        return( (cp1.cValue==cp2.cValue) && (cp1.xValue==cp2.xValue) && (cp1.yValue==cp2.yValue) ) 

At this point the methods are invoked with a specific class so there is no binary method issue. But I would like to define them outside the class in a Qualifier (like a mixin):

qualifier Comparable
  class methods
    equal(p1, p2: SelfType): bool
end qualifier

class PointClass is Comparable
...
  class methods
    equal(p1, p2: SelfType): bool is 
       return( (p1.xValue==p2.xValue) && (p1.yValue==p2.yValue) )  
end class

class ColorPointClass subclass of PointClass
...
  class methods
    equal(cp1, cp2: SelfType): bool is 
        return( (cp1.cValue==cp2.cValue) && (cp1.xValue==cp2.xValue) && (cp1.yValue==cp2.yValue) ) 
end class

...
b: bool := Comparable.equal(p1, p2)

Which method should be called when doing Comparable.equal? It will depend on both arguments. So I guess that is a form of multimethod. But with that scheme it is not possible to redefine eg. equal(p: PointClass; cp: ColorPointClass): bool so that makes it more limited than CLOS multimethods.

In certain, very limited

In certain, very, very limited cases you can get the effect (and name it whatever you want) in C++

template<typename MySubClass>
class MyClass {
  virtual MySubClass newInstance() = 0;
};

class ActualSubClass : public MyClass<ActualSubClass> {
  ActualSubClass newInstance() { ... }
};

CRTP

That's the Curiously recurring template pattern:
http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
however, if you have a more complex hierarchy, that doesn't work - you'd need ActualSubClass to take a parameter as well, and to have another real ActualSubClass.

template<typename MySubClass>
class MyClass {
  virtual MySubClass newInstance() = 0;
};
template<typename MySubClass>
class SubClass : public MyClass<MySubClass> {
  MySubClass newInstance() { ... }
};
class ActualSubClass: public SubClass<ActualSubClass> {
}
template <typename MySubClast>
class SubSubClass : public SubClass <MySubClass> {
  MySubClass newInstance() { ... }
};

class ActualSubSubClass: public SubSubClass <ActualSubSubClass> {
}

Now, however, you miss some interesting subtyping relationship. Maybe that could be fixed with multiple inheritance, with virtual inheritance to avoid duplication of the same supertype - but probably not, because templates are invariant. ActualSubSubClass descends from SubSubClass<ActualSubSubClass>, and therefore from SubClass<ActualSubSubClass>(=typeA), which is unrelated to SubClass<ActualSubClass> (=typeB) == ActualSubClass. Therefore, one would get an instance of typeA and one of typeB, even with virtual inheritance.

Two methods

In strong typed language, objects of different types should not be mixed together. What you are looking for is exactly mixing different types together to form something like ThisClassType MyClass::newInstance();.

Therefore, we have two choices. The firse choice is keeping the types of the objects. It can be done by creating two global functions:
MyClass MyClass_newInstance();
MySubClass MySubClass_newInstance();

Template can be used here to simplify or complicate the code.

The second choice is to downcast the types:
class MyClass {
  MyClass &newMyClassInstance();
}
class MySubClass : MyClass {
  MyClass &newMyClassInstance() {return newMySubClassInstance();}
  MySubClass &newMySubClassInstance();
}

In OCaml

OCaml also being, at least on paper, a "strongly typed object-oriented language", I think you may be interested in an OCaml solution to this problem.

The idea is that to give a name to the object type, you just add a type annotation on the "self" variable referring to the object (often named `this` in object-oriented languages; in OCaml it is a bound name and one may choose any variable name).

class virtual comparable = 
   object (self : ’a)
     method virtual leq : ’a -> bool
   end;;

There is a dynamic counterpart : one may want to produce an instance of the self type (which is not the same as an instance of the class being defined, as the self type may be a subclass). OCaml provides a syntax to build new instances of the self type, by specifying a subset of its internal variables (to be changed).

#class functional_point y =
   object 
     val x = y
     method get_x = x
     method move d = {< x = x + d >}
   end;;

(* inferred type *)
class functional_point :
  int ->
  object (’a) val x : int method get_x : int method move : int -> ’a end

This is described in the OCaml manual :

Scala

Sounds a bit like Scala's explicitly typed self references.