11

I am learning Delphi reading Marco Cantu's book and it's super complete. It's very clear but I have a doubt about the keyword self. I already have experience with OOP and I have the basics of it. My question is very simple. Can I compare the keyword self (Delphi) to the keyword this (Java)?

When I read on the book about the self used inside record, I got in my mind something like self : Delphi = this : Java. Look at the code I created to make a test:

type
 TMarioKart = packed record
   Character: String;
   Kart: String;
   Tires: String;
   Speed: double;
   Competitive: boolean;
  private
   air-speed: integer;
   ground-speed: integer;
   water-speed: integer;
  public
   constructor Create(Character: string);
   function ShowStats(a: TMarioKart):string; overload;
   function ShowStats(a: TMarioKart; b: TMarioKart): string; overload;
 end;

I am going to cut off the biggest part of the code, I am just showing the constructor here:

constructor TMarioKart.Create(Character: string);
begin
  self.Character := Character;
end;

Using the keyword self here I am referring to the Character of the record, and not to the Character passed in the method. Is this the correct way to use the self? Could it be the brother of Java's this?

Alberto Miola
  • 4,643
  • 8
  • 35
  • 49
  • 5
    Btw, you probably don't want to use packed records. They just lead to misaligned objects and inefficient memory access. – David Heffernan Aug 11 '16 at 10:40
  • Ok I am removing it, thanks – Alberto Miola Aug 11 '16 at 10:41
  • Also, constructors on records (value types) do give scope for confusion, and you might be better starting with classes rather than records. – David Heffernan Aug 11 '16 at 10:42
  • From what I can read, records and classes have different memory usages. There are like 200 pages about classes, and they are the reason why I got this book. I find record and classes very similar so far, but I'm sure that in a few days I'll have a better idea about them, – Alberto Miola Aug 11 '16 at 10:44
  • 1
    A more common convention IMO would be to use e.g. `TMarioKart.Create(ACharacter: string);` - note the `A` for the argument. and avoid the `self`. – kobik Aug 11 '16 at 10:46
  • 2
    You'll find out that they are poles apart when you come to write `A := B` where `A` and `B` are of type `TMarioKart`. With records you will copy the value, with classes you will copy the reference. – David Heffernan Aug 11 '16 at 10:50
  • 1
    BTW, I did not know Delphi allowed to use `-` with variable/field names. (i.e. `air-speed`)... – kobik Aug 11 '16 at 10:58
  • 3
    If its a special unicode character and not the ASCII character 45 then yes - but I would never ever ever do that - except for a prank ;) – Stefan Glienke Aug 11 '16 at 11:28
  • 1
    @Kobik, Please don't promote the `A` prefix convention for parameters. There is no need for that, because class/record members already have a `F` prefix. The RTL does not use that convention anymore, see: http://docwiki.embarcadero.com/Libraries/XE6/en/System.SysUtils.Format and many thousands of other examples. – Johan Aug 11 '16 at 13:47
  • A common convention is, however, to make string parameters `const`, if that is possible. And `air-speed`, etc. do indeed use the minus character, which is not allowed in Delphi. He could use `air_speed` but I would rather write FAirSpeed, in line with another convention. – Rudy Velthuis Aug 11 '16 at 14:45
  • The main difference between records and classes is that classes are reference types while record are value types. And records don't have inheritance or virtual methods, nor any hidden fields like a monitor field, a VMT pointer field, and fields for implemented interfaces. Classes can have those. – Rudy Velthuis Aug 11 '16 at 14:54
  • 1
    FWIW: Self is **not a keyword**. It is one of the special identifiers in Delphi that have a special meaning (like Exit, Break, Continue, Default, SizeOf, Ord, Pred, Prev, etc.), but it is not a keyword. It is, for most practical purposes, equivalent to the Java keyword `this`, though. – Rudy Velthuis Aug 11 '16 at 15:07
  • If Classes and Records were indeed so similar, then there wouldn't have been a separation of the two from the very beginning. There are almost endless reasons why they are different. Each with its own advantages and disadvantages. – Jerry Dodge Aug 11 '16 at 15:11
  • @Jerry: there are of course differences, but note that records have taken over some of the semantics (except inheritance and related functionality -- virtual, protected, etc.) of the Turbo-Pascal style `object` types, the forerunners of the `class` types as introduced in Delphi (1.0). – Rudy Velthuis Aug 11 '16 at 15:27
  • You may be interested in a deeper look in the hard life of the [self identifier - IOW: self is **not a keyword**](https://stackoverflow.com/a/57523517/2932052). – Wolf Aug 16 '19 at 11:07
  • @RudyVelthuis I tried a supplementary answer about the not-being-a-keyword aspect. Would you say it is technically correct? – Wolf Aug 16 '19 at 11:11

4 Answers4

15

Self is very similar to this in Java, C++, or C#. However it is a little bit more invoked, as the following code will show.

In Delphi, you can have class methods that are not static but also have a Self pointer, which then obviously does not point to an instance of the class but to the class type itself that the method is called on.

See the output of this program:

program WhatIsSelf;

{$APPTYPE CONSOLE}

type
  TAnimal = class
    procedure InstanceMethod;
    class procedure ClassMethod;
    class procedure StaticClassMethod; static;
  end;

  TDog = class(TAnimal)
  end;

class procedure TAnimal.ClassMethod;
begin
  Writeln(Self.ClassName);
end;

procedure TAnimal.InstanceMethod;
begin
  Writeln(Self.ClassName);
end;

class procedure TAnimal.StaticClassMethod;
begin
//  Writeln(Self.ClassName); // would not compile with error: E2003 Undeclared identifier: 'Self'
end;

var
  t: TAnimal;
begin
  t := TDog.Create;
  t.InstanceMethod;
  t.ClassMethod;

  TAnimal.ClassMethod;
  TDog.ClassMethod;

  Readln;
end.
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Stefan Glienke
  • 20,860
  • 2
  • 48
  • 102
  • 1
    In a Java static method, because `this` is always an instance, to refer to the class you need to use the name of the class, http://stackoverflow.com/questions/11664522/why-cant-we-use-this-keyword-in-a-static-method – David Heffernan Aug 11 '16 at 11:43
  • Note that `self` can also refer to non-objects when using record helpers for records or simple types. The only way to refer to the simple type is to use `self` even though there is no object in sight. AFAIK this has no analogue in Java. – Johan Aug 11 '16 at 12:02
4

Yes, Delphi's Self is the direct analogue of Java's this.

Johan
  • 74,508
  • 24
  • 191
  • 319
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 1
    @Johan The languages of course have differences. I don't feel that picking away at such nuances is particularly helpful for the asker. I think you are perhaps too buried in the detail here. Where `this` is meaningful in Java, `Self` has the same meaning in analagous code in Delphi. For sure there are places where `this` is not meaningful, but they are quite esoteric. For a beginner to the language, mapping `Self` to `this` is a good way to progress. It will be a while before the beginner is ready to deal with Delphi non-static class methods which have no analogue in Java. – David Heffernan Aug 11 '16 at 12:17
  • 1
    a so called ["lie-to-children"](https://en.wikipedia.org/wiki/Lie-to-children) (and that is not meant to insult -- it is simplifying complex things in order to describe them to children or lay-people, leaving out currently irrelevant nuances) – Rudy Velthuis Aug 11 '16 at 14:49
2

Formally speaking, Self is a normal identifier (that is automatically predeclared in some circumstances).

Self is automatically defined in the implementation of methods and class methods and its purpose there is similar to this in Java as already mentioned. The underlying technology is analogous to the Result variable in ordinary functions.

In other words, there is no self keyword (that's why it's typically written with an uppercase S). Whenever you want (and can [*]), you may introduce your own Self variable, method or class.

type
  // TForm1 ommitted

  Self = class
    function Self: Integer;
  end;

function Self.Self: Integer;
begin
  Result := SizeOf(Self);
end;

You'll have of course difficulties to instantiate an object of this type within a method, in these cases, you have to use it through an adapter function (or procedure):

function UseSelf: Integer;
var
  S: Self;
begin
  S := Self.Create;
  Result := S.Self;
  S.Free;
end;

function VarSelf: Integer;
var
  Self: Integer;
begin
  Self := SizeOf(Result);
  Result := Self;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(IntToStr(UseSelf)+' '+IntToStr(VarSelf));
end;


[*] You cannot declare a Self variable within methods, because there is already such a declaration and that's exactly what the error says:

Identifier redeclared: 'Self'

Wolf
  • 9,679
  • 7
  • 62
  • 108
-1

self is a special variable that points to the object that owns the currently executing code and it gives access to the current object. In Ruby programming language there is self too, however equivalent of it in JavaScript, C++, C# and Java is this and in VB is Me.

gyousefi
  • 306
  • 3
  • 9