Delphi Self keyword
Asked Answered
P

4

12

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?

Pneumodynamics answered 11/8, 2016 at 10:36 Comment(16)
Btw, you probably don't want to use packed records. They just lead to misaligned objects and inefficient memory access.Demolish
Ok I am removing it, thanksPneumodynamics
Also, constructors on records (value types) do give scope for confusion, and you might be better starting with classes rather than records.Demolish
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,Pneumodynamics
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.Montagnard
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.Demolish
BTW, I did not know Delphi allowed to use - with variable/field names. (i.e. air-speed)...Montagnard
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 ;)Outthink
@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: docwiki.embarcadero.com/Libraries/XE6/en/System.SysUtils.Format and many thousands of other examples.Vanward
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.Discursive
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.Discursive
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.Discursive
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.Emmeram
@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).Discursive
You may be interested in a deeper look in the hard life of the self identifier - IOW: self is not a keyword.Rabideau
@RudyVelthuis I tried a supplementary answer about the not-being-a-keyword aspect. Would you say it is technically correct?Rabideau
D
4

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

Demolish answered 11/8, 2016 at 10:39 Comment(2)
@Vanward 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.Demolish
a so called "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)Discursive
O
16

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.
Outthink answered 11/8, 2016 at 11:39 Comment(2)
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, #11665022Demolish
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.Vanward
D
4

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

Demolish answered 11/8, 2016 at 10:39 Comment(2)
@Vanward 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.Demolish
a so called "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)Discursive
R
3

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'

Rabideau answered 16/8, 2019 at 11:4 Comment(0)
V
-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.

Vassallo answered 26/7, 2020 at 13:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.