<p>In the class definitions of an object oriented language, <code>this</code> refers to the object instance the code is about to work upon. Naturally, it should have the same type as the class to be defined. But there are variations of a type that could also be applied to <code>this</code>. <code>self</code> is sometimes an alternative name to <code>this</code>, but sometimes could also refer to the class itself, instead of the object.</p>
<p>To demonstrate, a simple example in C++ would be:</p>
<pre class="lang-cpp prettyprint-override"><code>class T {
public:
    int f() const {
        // &quot;this&quot; is in (const T*), instead of just (T*)
    }
}
</code></pre>
<p>The answer may seem obvious at first glance: For every variation that could be applied to the parameters, it could also be applied to <code>this</code>. If parameters could be a constant, <code>this</code> could be constant. If parameters could be a rvalue reference, <code>this</code> could be defined as a rvalue reference. (There could be another question for that if anyone is interested.) Object oriented programming works like syntactic sugar over the traditional procedural programming in many cases, after all.</p>
<p>But there are also situations that this logic couldn't be applied easily. Notably, the <a href="https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern" rel="nofollow noreferrer">curiously recurring template pattern</a>
(CRTP) refers to something like this:</p>
<pre class="lang-cpp prettyprint-override"><code>class Derived : public Base&lt;Derived&gt;
</code></pre>
<p>It is implied that code in <code>Base</code> may need to access the type <code>Derived</code> somewhere. <code>Derived</code> is something like the real type of <code>this</code>. CRTP has the obvious disadvantages such as being less intuitive, and making casts between base classes and subclasses difficult. It might be better if we turn it into another variation of <code>this</code>.</p>
<p>But template and generics are too general, that could be used as catch-all solutions to implement many different things, even if it is not optimal. Having CRTP may even make people less likely to report their use case, which may not be covered in a specific variation-of-<code>this</code> solution.</p>
<p>So, <strong>what are the variations to the type of <code>this</code> or <code>self</code> that should be supported?</strong> I.e. what useful differences could be made to <code>this</code> or <code>self</code>, from just an object of the class to be defined, or just the class, using different declarations of a block of code?</p>
<p>CRTP could be a source of many different variations. But there might be also cases not covered by CRTP.</p>
<h3>Note</h3>
<ul>
<li>This is not about whether <code>this</code> should be a pointer or a reference, or implicit, as they are almost equivalent. I'm more interested in things that could not be done in other types of <code>this</code>. I.e. It's objectively a valid answer if something could not be done, or could not be done safely in languages without one kind of variation. Say if we have a language like C++ that doesn't support the <a href="https://en.cppreference.com/w/cpp/language/member_functions#Member_functions_with_cv-qualifiers" rel="nofollow noreferrer">const qualifier</a> in the example, calling a method in a constant object would be either impossible, or unsafe as it would use the non-const <code>this</code> in the method. So const is a valid answer, although trivial and already widely known.</li>
<li>This is not a survey about how things are done in every language. It's about what are the <em>use cases</em> to be covered, or how problems are solved if there are multiple ways.</li>
<li>The very traditional things that are applied to any parameters, such as const and rvalue reference, should be better in a separate question, if there is. But they could be referenced if there are some overlaps.</li>
</ul>

<types><static-typing><object-oriented>
What are the possible variations of the type of "this" or "self"?
CC BY-SA 4.0
2023-07-21T09:07:05.123Z
I'm posting this question so that information related to [this answer](https://langdev.stackexchange.com/a/2461/1149) has somewhere to go. But I'm not sure the answer itself could be moved here.
user23013
CC BY-SA 4.0
2023-07-21T09:07:31.010Z
You've set out some things that this question *isn't*, but I'm not sure I can tell precisely what it **is** about. It does feel very broad, at least.
Michael Homer
CC BY-SA 4.0
2023-07-21T09:30:59.697Z
@MichaelHomer Is it clearer? I think this is much more restrictive than the question devised in the comment of that answer: "Pros and cons of having a this with a non-fixed type?"
user23013
CC BY-SA 4.0
2023-07-21T09:41:45.240Z
@MichaelHomer A possible way to clear up the question is to remove everything related to CRTP, and move them to an answer, if it doesn't discourage more answers related to CRTP.
user23013
CC BY-SA 4.0
2023-07-21T09:48:55.320Z
It seems both very embedded in the C++ milieu and very unconstrained: "what are some things that you could do with `this`?". It explicitly rules out substantiating evidence, and requiring strong uniqueness between answers doesn't seem to fit the Q+A model here. I'm not sure we're equipped to deal with this question as it's currently set out, and I'm not sure what answer it expects except the reference one - but as you say, that wouldn't fit the question either.
Michael Homer
CC BY-SA 4.0
2023-07-21T10:21:49.550Z
I prefer calling it statically typed, instead of C++ milieu. For most things you could do with `this`, you could just write a function using `this` as a parameter, and doesn't require language support. It's like saying, "what are some things that you could do with this, that needs language support and could not or should not be done using just a function?" I think it's actually difficult to get even one answer beyond the examples such as `const`.
user23013
CC BY-SA 4.0
2023-07-21T11:58:58.890Z
Would an answer mentioning the special covariant `Self` type in Swift be on the table? For example, the equality operator is `static func ==(lhs: Self, rhs: Self) -> Bool`. I agree with Michael that it’s non-obvious what the question _is_.
Bbrk24
CC BY-SA 4.0
2023-07-21T12:53:27.177Z
I don't think this is too broad but it is a little unclear. I think it is to be interpreted as "what use cases are the for self references in an OO langugage".  So maybe having "this/self" be either the type itself (as normal) or a supertype or a subtype as well as const and non-const variations. Phrased that way it would be clear and easier to answer. That is assuming that is the intended question of course.
Bruce Adams
CC BY-SA 4.0
2023-07-22T11:52:46.560Z
@Bbrk24 If I understood it correctly, it might be an answer, as it is different from the `self` in many other languages. But it may need some thinking, as this might also be the case in my comment to the linked answer, that "it would be helpful to access `this` in different types by using different calls in the same function".
user23013
CC BY-SA 4.0
2023-07-22T11:54:45.487Z
@BruceAdams I think that's basically what it asks. But "use cases of this" sounds much more broad than this.
user23013
CC BY-SA 4.0
2023-07-27T21:52:23.027Z
"I prefer calling it statically typed, instead of C++ milieu." The issues you're describing don't seem to make sense inherently in statically typed languages considered generally. Quite a few of them don't even support generic types, never mind the ability to implement something like CRTP.
Karl Knechtel
CC BY-SA 4.0
2023-07-27T21:54:40.880Z
I *think* what you might be trying to get at is something like "what namespaces related to an object could make sense to check implicitly?" - looking to go beyond the obvious such as "attributes of the current object", "attributes defined in a base class" etc.
Karl Knechtel
CC BY-SA 4.0
2023-08-01T00:42:36.123Z
@KarlKnechtel You say quite a few of them are unable to do something. Isn't that the point? Some languages cannot do X, so we find it is because it lacks a minimal feature Y, so we isolated a distinct property Y and Y might be an answer. Dynamically typed languages are not so relevant, exactly because you could usually do whatever you want about types without pain, in the exact opposite of having no ability to do something at all. And no, this is not about namespaces. It could be related to namespaces with some interpretation, but it is the part we usually mix up while considering namespaces.
user23013
<p>This isn't a complete answer to the question, but a similar issue is common when methods are designed for chaining. For example, in Java:</p>
<pre class="lang-java prettyprint-override"><code>class Foo {
    int x = 0;
    Foo incrementX() {
        x++;
        return this;
    }
    Foo printX() {
        System.out.println(x);
        return this;
    }
}
</code></pre>
<p>That is, the methods are supposed to return the same instance, to allow for chains like <code>foo.incrementX().printX()</code>. The problem comes when a subclass is defined:</p>
<pre class="lang-java prettyprint-override"><code>class Bar extends Foo {
    int y = 0;
    Bar incrementY() {
        y++;
        return this;
    }
}
</code></pre>
<p><code>Bar</code> inherits the methods from <code>Foo</code>, but since their return type is <code>Foo</code>, it is not possible to chain methods like <code>bar.incrementX().incrementY()</code>. Hence the need for the &quot;curiously repeating template pattern&quot; in languages like C++ and Java.</p>
<p>On the other hand, Typescript has an elegant solution: <code>this</code> can be used as a type, to mean &quot;the type of the expression <code>this</code>&quot;, i.e. the type of the subject of the method call. In Typescript, the above example could be written like</p>
<pre class="lang-typescript prettyprint-override"><code>class Foo {
    x: number = 0;
    incrementX(): this { ... }
    printX(): this { ... }
}
class Bar extends Foo {
    y: number = 0;
    incrementY(): this { ... }
}
</code></pre>
<p>And now the chain <code>bar.incrementX().incrementY()</code> is valid, because the return type of <code>incrementX()</code> is resolved to be the type of the method subject, <code>bar</code>. Typescript calls this type the &quot;<a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html#polymorphic-this-types" rel="nofollow noreferrer">polymorphic <code>this</code> type</a>&quot;.</p>

CC BY-SA 4.0
2023-07-27T21:48:31.737Z
2023-07-27T21:48:31.737Z
kaya3
<h2>Swift's covariant <code>Self</code></h2>
<p>Expanding on <a href="https://langdev.stackexchange.com/a/2596/">@kaya3's answer</a>, Swift has a special <code>Self</code> type that behaves differently depending on where it's used.</p>
<p>Within a struct, enum, or final class, <code>Self</code> has an obvious, fixed meaning, since these types cannot be derived from.</p>
<p>Within a protocol, <code>Self</code> means &quot;the type implementing this protocol&quot;. Implementers fill it in accordingly:</p>
<pre class="lang-swift prettyprint-override"><code>protocol AdditiveArithmetic {
  static func + (lhs: Self, rhs: Self) -&gt; Self
}

extension Int: AdditiveArithmetic {
  static func + (lhs: Int, rhs: Int) -&gt; Int { ... }
}

extension UInt: AdditiveArithmetic {
  static func + (lhs: UInt, rhs: UInt) -&gt; UInt { ... }
}

// etc
</code></pre>
<p>These first two usages are different from TypeScript's <code>this</code> type, which always represents the value of <code>this</code> and never something else of the same type.</p>
<p>Within a non-final class, <code>Self</code> is more complicated.</p>
<p>In covariant position, such as a function return type, <code>Self</code> is only allowed if the value is <code>self</code> or another expression of type <code>Self</code>. This is the same rule as in TypeScript.</p>
<pre class="lang-swift prettyprint-override"><code>class C {
  func foo() -&gt; Self {
    self // okay
  }

  func bar() -&gt; Self {
    foo() // okay
  }

  func baz() -&gt; Self {
    C() // not okay
  }
}
</code></pre>
<p>Note that this becomes complicated in <code>static</code> methods, since you don't have access to a <code>self</code>. Swift deals with this using <code>required init</code>:</p>
<pre class="lang-swift prettyprint-override"><code>class C1 {
  required init(foo: Void) {}
  init(bar: Void) {}

  static func foo() -&gt; Self {
    .init(foo: ()) // okay
  }

  static func bar() -&gt; Self {
    .init(bar: ()) // error
    // Because init(bar:) isn't required, subclasses might not implement it.
  }
}

class C2: C1  {
  required init(foo: Void) {
    // Because init(foo:) is required, you must override it.
    super.init(foo: ())
  }
}
</code></pre>
<p>In contravariant position, such as an argument, it is forbidden. You are required to replace it with the class name:</p>
<pre class="lang-swift prettyprint-override"><code>class C {
  func foo(_ other: Self) {}
  // error: covariant 'Self' or 'Self?' can only appear as the type of a property, subscript or method result; did you mean 'C'?
}
</code></pre>
<p>This combines weirdly with the protocol rule above, due to the Liskov substitution principle:</p>
<pre class="lang-swift prettyprint-override"><code>protocol P {
  func foo(_ other: Self)
}

protocol Q {
  func bar(_ other: Self)
}

class C1 {
  func foo(_ other: C1) {}
}

class C2: C1, Q {
  override func foo(_ other: C1) {} // This 'Self' becomes C1...
  func bar(_ other: C2) {} // ...but this 'Self' becomes C2...
}

let x = C1(), y = C2()

(y as C1).foo(x) // ...because this is legal...
(y as C1).bar(x) // ...but this isn't.
</code></pre>
<p>In invariant position, such as <code>inout</code> arguments to functions, <code>Self</code> is just illegal.</p>
<pre class="lang-swift prettyprint-override"><code>protocol Incrementable {
  static func += (lhs: inout Self, rhs: Self)
}

class C: Incrementable {
  static func += (lhs: inout Self, rhs: C) {}
  // error: protocol 'Incrementable' requirement '+=' cannot be satisfied by a non-final class ('C') because it uses 'Self' in a non-parameter, non-result type position
}
</code></pre>
<p>I'd say that referring to invariant position as &quot;non-parameter, non-result type position&quot; is a bit misleading: <code>lhs</code> here isn't <em>neither</em>, it's <em>both</em>.</p>

CC BY-SA 4.0
2023-07-28T20:19:35.867Z
2023-07-28T20:19:35.867Z
Bbrk24
# What are the possible variations of the type of "this" or "self"?
Posted by: username_0 on 2023-07-21
In the class definitions of an object oriented language, this refers to the object instance the code is about to work upon. Naturally, it should have the same type as the class to be defined. But there are variations of a type that could also be applied to this. self is sometimes an alternative name to this, but sometimes could also refer to the class itself, instead of the object.
To demonstrate, a simple example in C++ would be:
class T {
public:
    int f() const {
        // "this" is in (const T*), instead of just (T*)
    }
}

The answer may seem obvious at first glance: For every variation that could be applied to the parameters, it could also be applied to this. If parameters could be a constant, this could be constant. If parameters could be a rvalue reference, this could be defined as a rvalue reference. (There could be another question for that if anyone is interested.) Object oriented programming works like syntactic sugar over the traditional procedural programming in many cases, after all.
But there are also situations that this logic couldn't be applied easily. Notably, the curiously recurring template pattern
(CRTP) refers to something like this:
class Derived : public Base

It is implied that code in Base may need to access the type Derived somewhere. Derived is something like the real type of this. CRTP has the obvious disadvantages such as being less intuitive, and making casts between base classes and subclasses difficult. It might be better if we turn it into another variation of this.
But template and generics are too general, that could be used as catch-all solutions to implement many different things, even if it is not optimal. Having CRTP may even make people less likely to report their use case, which may not be covered in a specific variation-of-this solution.
So, what are the variations to the type of this or self that should be supported? I.e. what useful differences could be made to this or self, from just an object of the class to be defined, or just the class, using different declarations of a block of code?
CRTP could be a source of many different variations. But there might be also cases not covered by CRTP.
Note

This is not about whether this should be a pointer or a reference, or implicit, as they are almost equivalent. I'm more interested in things that could not be done in other types of this. I.e. It's objectively a valid answer if something could not be done, or could not be done safely in languages without one kind of variation. Say if we have a language like C++ that doesn't support the const qualifier in the example, calling a method in a constant object would be either impossible, or unsafe as it would use the non-const this in the method. So const is a valid answer, although trivial and already widely known.
This is not a survey about how things are done in every language. It's about what are the use cases to be covered, or how problems are solved if there are multiple ways.
The very traditional things that are applied to any parameters, such as const and rvalue reference, should be better in a separate question, if there is. But they could be referenced if there are some overlaps.
**Tags:** types static-typing object-oriented
> **Comments:**
> **username_0**: I'm posting this question so that information related to [this answer](https://langdev.stackexchange.com/a/2461/1149) has somewhere to go. But I'm not sure the answer itself could be moved here.  
> **username_1**: You've set out some things that this question *isn't*, but I'm not sure I can tell precisely what it **is** about. It does feel very broad, at least.  
> **username_0**: @MichaelHomer Is it clearer? I think this is much more restrictive than the question devised in the comment of that answer: "Pros and cons of having a this with a non-fixed type?"  
> **username_0**: @MichaelHomer A possible way to clear up the question is to remove everything related to CRTP, and move them to an answer, if it doesn't discourage more answers related to CRTP.  
> **username_1**: It seems both very embedded in the C++ milieu and very unconstrained: "what are some things that you could do with `this`?". It explicitly rules out substantiating evidence, and requiring strong uniqueness between answers doesn't seem to fit the Q+A model here. I'm not sure we're equipped to deal with this question as it's currently set out, and I'm not sure what answer it expects except the reference one - but as you say, that wouldn't fit the question either.  
> **username_0**: I prefer calling it statically typed, instead of C++ milieu. For most things you could do with `this`, you could just write a function using `this` as a parameter, and doesn't require language support. It's like saying, "what are some things that you could do with this, that needs language support and could not or should not be done using just a function?" I think it's actually difficult to get even one answer beyond the examples such as `const`.  
> **username_2**: Would an answer mentioning the special covariant `Self` type in Swift be on the table? For example, the equality operator is `static func ==(lhs: Self, rhs: Self) -> Bool`. I agree with Michael that it’s non-obvious what the question _is_.  
> **username_3**: I don't think this is too broad but it is a little unclear. I think it is to be interpreted as "what use cases are the for self references in an OO langugage".  So maybe having "this/self" be either the type itself (as normal) or a supertype or a subtype as well as const and non-const variations. Phrased that way it would be clear and easier to answer. That is assuming that is the intended question of course.  
> **username_0**: @Bbrk24 If I understood it correctly, it might be an answer, as it is different from the `self` in many other languages. But it may need some thinking, as this might also be the case in my comment to the linked answer, that "it would be helpful to access `this` in different types by using different calls in the same function".  
> **username_0**: @BruceAdams I think that's basically what it asks. But "use cases of this" sounds much more broad than this.  
> **username_4**: "I prefer calling it statically typed, instead of C++ milieu." The issues you're describing don't seem to make sense inherently in statically typed languages considered generally. Quite a few of them don't even support generic types, never mind the ability to implement something like CRTP.  
> **username_4**: I *think* what you might be trying to get at is something like "what namespaces related to an object could make sense to check implicitly?" - looking to go beyond the obvious such as "attributes of the current object", "attributes defined in a base class" etc.  
> **username_0**: @KarlKnechtel You say quite a few of them are unable to do something. Isn't that the point? Some languages cannot do X, so we find it is because it lacks a minimal feature Y, so we isolated a distinct property Y and Y might be an answer. Dynamically typed languages are not so relevant, exactly because you could usually do whatever you want about types without pain, in the exact opposite of having no ability to do something at all. And no, this is not about namespaces. It could be related to namespaces with some interpretation, but it is the part we usually mix up while considering namespaces.  
---
## 2 answers
### Answer by username_2 on 2023-07-28. Score: 7
Swift's covariant Self
Expanding on @kaya3's answer, Swift has a special Self type that behaves differently depending on where it's used.
Within a struct, enum, or final class, Self has an obvious, fixed meaning, since these types cannot be derived from.
Within a protocol, Self means "the type implementing this protocol". Implementers fill it in accordingly:
protocol AdditiveArithmetic {
  static func + (lhs: Self, rhs: Self) -> Self
}

extension Int: AdditiveArithmetic {
  static func + (lhs: Int, rhs: Int) -> Int { ... }
}

extension UInt: AdditiveArithmetic {
  static func + (lhs: UInt, rhs: UInt) -> UInt { ... }
}

// etc

These first two usages are different from TypeScript's this type, which always represents the value of this and never something else of the same type.
Within a non-final class, Self is more complicated.
In covariant position, such as a function return type, Self is only allowed if the value is self or another expression of type Self. This is the same rule as in TypeScript.
class C {
  func foo() -> Self {
    self // okay
  }

  func bar() -> Self {
    foo() // okay
  }

  func baz() -> Self {
    C() // not okay
  }
}

Note that this becomes complicated in static methods, since you don't have access to a self. Swift deals with this using required init:
class C1 {
  required init(foo: Void) {}
  init(bar: Void) {}

  static func foo() -> Self {
    .init(foo: ()) // okay
  }

  static func bar() -> Self {
    .init(bar: ()) // error
    // Because init(bar:) isn't required, subclasses might not implement it.
  }
}

class C2: C1  {
  required init(foo: Void) {
    // Because init(foo:) is required, you must override it.
    super.init(foo: ())
  }
}

In contravariant position, such as an argument, it is forbidden. You are required to replace it with the class name:
class C {
  func foo(_ other: Self) {}
  // error: covariant 'Self' or 'Self?' can only appear as the type of a property, subscript or method result; did you mean 'C'?
}

This combines weirdly with the protocol rule above, due to the Liskov substitution principle:
protocol P {
  func foo(_ other: Self)
}

protocol Q {
  func bar(_ other: Self)
}

class C1 {
  func foo(_ other: C1) {}
}

class C2: C1, Q {
  override func foo(_ other: C1) {} // This 'Self' becomes C1...
  func bar(_ other: C2) {} // ...but this 'Self' becomes C2...
}

let x = C1(), y = C2()

(y as C1).foo(x) // ...because this is legal...
(y as C1).bar(x) // ...but this isn't.

In invariant position, such as inout arguments to functions, Self is just illegal.
protocol Incrementable {
  static func += (lhs: inout Self, rhs: Self)
}

class C: Incrementable {
  static func += (lhs: inout Self, rhs: C) {}
  // error: protocol 'Incrementable' requirement '+=' cannot be satisfied by a non-final class ('C') because it uses 'Self' in a non-parameter, non-result type position
}

I'd say that referring to invariant position as "non-parameter, non-result type position" is a bit misleading: lhs here isn't neither, it's both.
---
### Answer by username_5 on 2023-07-27. Score: 4
This isn't a complete answer to the question, but a similar issue is common when methods are designed for chaining. For example, in Java:
class Foo {
    int x = 0;
    Foo incrementX() {
        x++;
        return this;
    }
    Foo printX() {
        System.out.println(x);
        return this;
    }
}

That is, the methods are supposed to return the same instance, to allow for chains like foo.incrementX().printX(). The problem comes when a subclass is defined:
class Bar extends Foo {
    int y = 0;
    Bar incrementY() {
        y++;
        return this;
    }
}

Bar inherits the methods from Foo, but since their return type is Foo, it is not possible to chain methods like bar.incrementX().incrementY(). Hence the need for the "curiously repeating template pattern" in languages like C++ and Java.
On the other hand, Typescript has an elegant solution: this can be used as a type, to mean "the type of the expression this", i.e. the type of the subject of the method call. In Typescript, the above example could be written like
class Foo {
    x: number = 0;
    incrementX(): this { ... }
    printX(): this { ... }
}
class Bar extends Foo {
    y: number = 0;
    incrementY(): this { ... }
}

And now the chain bar.incrementX().incrementY() is valid, because the return type of incrementX() is resolved to be the type of the method subject, bar. Typescript calls this type the "polymorphic this type".
---
