I hope to make some Class D heritage and implements all properties and methods of Interfaces A,B and C. Please help-me with an example in Delphi.
I use Delphi Xe7
How One class Implement Many Interfaces?
I'm trying something like:
Unit1
Type
IRefresher = Interface
['{B289720C-FFA4-4652-9F16-0826550DFCF9}']
procedure Refresh;
function getRefreshed: boolean;
property Refreshed:Boolean read getRefreshed;
End;
Unit2
Type
IRecorder = Interface
['{AB447097-C654-471A-A06A-C65CE5606721}']
procedure Reader;
procedure Writer;
end;
Unit3
ICustomer=Interface ['{F49C0018-37DA-463D-B5B4-4ED76416C7D4}']
procedure SetName(Value:String);
procedure SetDocument(Value:String);
function getName:String;
function getDocument:String;
End;
Unit4
Uses Unit1,Unit2,Unit3;
TGovernmentCustomer = class(TInterfacedObject, ICustomer, IRecorder,
IRefresher)
a: String;
public
{$REGION 'Customer'}
procedure SetName(Value: String); override;
procedure SetDocument(Value: String);
function getName: String; override;
function getDocument: String; override;
{$ENDREGION}
{$REGION 'Recorder'}
procedure Reader; override;
procedure Writer; override;
{$ENDREGION}
{$REGION 'Refresher'}
procedure Refresh; override;
function getRefreshed: boolean; override;
{$ENDREGION}
End;
It not works, because of many errors, such as 'Refresh not found in base class',
You have at least 3 implementation options for this:
1) virtual and abstract methods. In this case, you cannot instantiate this class and you must override abstract methods in descendant classes. Such methods would look like this:
type
TGovernmentCustomer = class(TInterfacedObject, ICustomer, IRecorder, IRefresher)
a: String;
public
procedure SetName(Value: String); virtual; abstract;
end;
There is no implementation, once the method is abstract.
2) virtual methods. In this case, you can instantiate this class and you may override some virtual methods in descendant classes. Such methods would look like this:
type
TGovernmentCustomer = class(TInterfacedObject, ICustomer, IRecorder, IRefresher)
a: String;
public
procedure SetName(Value: String); virtual;
end;
implementation
procedure TGovernmentCustomer.SetName(Value: String);
begin
// do something here. You can also leave it empty
end;
3) Static methods. In this case, you can instantiate this class and you cannot override static methods in descendant classes. Such methods would look like this:
type
TGovernmentCustomer = class(TInterfacedObject, ICustomer, IRecorder, IRefresher)
a: String;
public
procedure SetName(Value: String);
end;
implementation
procedure TGovernmentCustomer.SetName(Value: String);
begin
// do something here. This will be the behavior of all instances of this class and descendant classes if they exist
end;
One last note: Case (3) has the best performance. Calling virtual methods on interfaces has a performance penalty that may or may not be relevant in your specific application.
PS: As pointed out by Stefan, my link to another SO question was wrong. However, you can read about performance of virtual methods called through an interface from Andreas Hausladen blog: http://andy.jgknet.de/blog/2016/05/whats-wrong-with-virtual-methods-called-through-an-interface/
Remove the override word from your code as there is no explicit method binding directive for the interface method implementation. The override directive you've used in your code applies just for the virtual (abstract) or dynamic class methods of an ancestor class that are about to be implemented by the current class.
Here's an example that demonstrates a meaning of the override directive with a pseudo-abstract class that uses interfaces (sample from your code):
type
ICustomer = interface
['{F49C0018-37DA-463D-B5B4-4ED76416C7D4}']
procedure SetName(Value: string);
end;
IRefresher = interface
['{B289720C-FFA4-4652-9F16-0826550DFCF9}']
procedure Refresh;
end;
// sort of "abstract" class (not precisely) that does not yet "implement"
// the methods of the interfaces, only "includes" the interfaces
TAnyCustomer = class(TInterfacedObject, ICustomer, IRefresher)
private
FSomething: string;
public
// though the interfaces are "included" as a part of this class, their
// method implementation is not yet specific (missing implementantion
// exception is raised only, which is self-explaining, I'd say); that
// "virtual" directive of the following class methods lets this class'
// descendants "override" them to write the specific implementation
procedure SetName(Value: string); virtual;
procedure Refresh; virtual;
end;
// specific implementation of the class defined above; here you "override"
// the virtual methods of the "abstract" class defined above and implement
// the specific behavior of the class
TGovernmentCustomer = class(TAnyCustomer)
public
// "override" the ancestor's class method behavior and write a specific
// implementation (which finally implements some specific functionality
// here)
procedure SetName(Value: string); override;
procedure Refresh; override;
end;
implementation
procedure TAnyCustomer.SetName(Value: string);
begin
raise ENotImplemented.Create('Ouch! You missed to implement me!');
end;
procedure TAnyCustomer.Refresh;
begin
raise ENotImplemented.Create('Ouch! You missed to implement me!');
end;
procedure TGovernmentCustomer.SetName(Value: string);
begin
ShowMessage('I''m a government customer. How can I increase your budget?');
end;
procedure TGovernmentCustomer.Refresh;
begin
ShowMessage('Tell someone I''m fresh!');
end;
Related
I think DELPHI language offers a very clear and beautiful implementation of data encapsulation
via the property methods and clear getter and setter functions.
I want to access a class string list strlst via a getter and setter functions.
Option #1 in the code sample works fine as expected , but option #2 calling the
Stringlist.Commatext function does actually not work.
Is this a DELPHI bug or did I miss something with respect to class design?
Target : fill class stringlist without creating an external Tstringlist class, just pass commatext.
program Project2;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils, classes;
type
TSimpleClass = class
FStrlst: TStringList;
private
procedure SetStrList(const Value: TStringList);
public
constructor Create;
property strlst: TStringList read FStrlst write SetStrList;
end;
{ TSimpleClass }
constructor TSimpleClass.Create;
begin
inherited;
FStrlst := TStringList.Create;
end;
procedure TSimpleClass.SetStrList(const Value: TStringList);
var
i: Integer;
begin
Writeln('class getter / setter function is called ');
for i := 0 to Value.Count - 1 do
begin
FStrlst.Add(Value[i]);
end;
writeln ('content of internal strlist : ' + FStrlst.CommaText )
end;
begin
var
aSimpleClass: TSimpleClass;
var
testLst: TStringList;
try
aSimpleClass := TSimpleClass.Create;
try
// option #1 is working
testLst:=TStringList.Create;
testLst.CommaText := 'a,b,c';
aSimpleClass.strlst := testLst;
// option #2 not working ... this code should also call the
// setter function
aSimpleClass.strlst.commatext := 'd,e,f';
finally
aSimpleClass.Free;
end;
writeln ('done sample code !');
Readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
cmd line window sample output
output of this sample code
Is this a DELPHI bug or did I miss something with respect to class design?
No, it is not a Delphi bug, but a misunderstanding on your part. You say "property, getter and setter function not called", and I understand you refer to getter and setter for aSimpleClass.strlst.
You have defined direct read access (of FStrLst) for TSimpleClass.strlst, thus there is no getter to be called when reading (as in // option #2), and aSimpleClass.strlst refers directly to FStrLst.
The CommaText property of TStringList has its own setter and that is called in // option #2
Edit
Or, if your intention is to not expose the TStringList at all, but only its CommaText property, that is OK as follows:
Make sure the TStringList is private, as well as a getter and setter for CommaText, and add the property CommaTxt
TSimpleClass
private
FStrlst: TStringList;
...
function GetCommaText: string;
procedure SetCommaText(s: string);
public
property CommaTxt: string read GetCommaText write SetCommaText;
...
end;
Implement the getter and setter:
function TSimpleClass.GetCommaText: string;
begin
result := FStrlst.CommaText;
end;
procedure TSimpleClass.SetCommaText(s: string);
begin
FStrLst.CommaText := s;
end;
Now you can access the CommaTxt property without exposing the TStringList.
The reason why your option #2 doesn't fire the setter mthod is because in your option #2 you are not assigning any value to your strlst but insteadyou are interacting with the object that is being returned by the said property.
You see when you call aSimpleClass.strlst.commatext := 'd,e,f'; what happens is next:
Getter method of the strlst property is being called in order to return the reference to the TStringList object (the object thype that is defined by property)
Then the string value of d,e,f is assigned to the ComaText property that belongs to the String List whose reference was returned by your property getter method.
Now if at this time the TStringList that is part of your class would still not have been created an Access Violation would have been raised since you would be trying to access property of a non existent object.
I've just started developing with Delphi. I just wanted to work with the object. The structure I made is simple. Is there a point I missed?
I created a class in a unit called Unit2.
a. I created a string variable in this class I created (in Public section).
I added Unit2 to the uses section in Unit1.
a. I reached the global variable in Unit2 and changed its value.
I added Unit2 to Unit3 where I created it.
Now I'm trying to access this data I changed from Unit3.
unit Unit2;
interface
type
Gazi = class
private
{ private declarations }
public
RektorAdi : String;
{ public declarations }
end;
implementation
end.
unit Unit1;
interface
uses
..., Unit2, Unit3;
type
.. (Form Creating)
var
(Form create)
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
newElement: Gazi;
begin
newElement.RektorAdi := 'Pala';
Label1.Caption := 'Successfully';
Form3.Show;
end;
end.
unit Unit3;
interface
uses
... , Unit2;
type
(Form creating codes)
var
(Form codes)
implementation
{$R *.dfm}
procedure TForm3.Button1Click(Sender: TObject);
var
access: Gazi;
begin
Label1.Caption := access.RektorAdi;
end;
end.
I expect the output of 'Pala' (my change to the Unit1) but the actual output is '册['. I don't even know what language my results are.
In addition to all this, when I try to close the program, I get an error:
Exception EAccessViolation in module Project1exe at 0000848F. Access violation at adress 0040848F in module 'Project1.exe'. Read of adress 3BC03BBC.
In Unit1, you are not instantiating the newElement object before writing to its RektorAdi member, so you are trashing random memory.
In Unit3, you are not instantiating the access object before accessing its RektorAdi member, so you are reading from invalid memory.
To do what you are attempting (set the RektorAdi value in one unit and then access it in another unit), you need a singleton object that both units can share, eg:
unit Unit2;
interface
type
Gazi = class
private
{ private declarations }
public
RektorAdi : String;
{ public declarations }
end;
var
GlobalGazi: Gazi;
implementation
initialization
GlobalGazi := Gazi.Create;
finalization
GlobalGazi.Free;
end.
unit Unit1;
interface
uses
...;
type
.. (Form Creating)
var
(Form create)
implementation
uses
Unit2, Unit3;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
GlobalGazi.RektorAdi := 'Pala';
Label1.Caption := 'Successfully';
Form3.Show;
end;
end.
unit Unit3;
interface
uses
...;
type
(Form creating codes)
var
(Form codes)
implementation
uses
Unit2;
{$R *.dfm}
procedure TForm3.Button1Click(Sender: TObject);
begin
Label1.Caption := GlobalGazi.RektorAdi;
end;
end.
type
Gazi = class
private
{ private declarations }
public
{ public declarations }
RektorAdi : String;
end;
procedure TForm1.Button1Click(Sender: TObject);
var newElement: Gazi;
begin
newElement.RektorAdi :='Pala';
Label1.Caption := 'Successfully';
Form3.Show;
end;
You don't instantiate (allocate) the space needed for the "newElement" class. All classes must be created by calling a constructor, which instantiates (allocates and initializes) the variable to point to the proper class.
You'll need to do this:
newElement := Gazi.Create;
newElement.RektorAdi :='Pala';
Now, this will ensure that you don't get the access violation when you attempt to assign a string to the member field RektorAdi, but it doesn't solve the problem altogether.
newElement is a LOCAL variable, which means that it is only visible (and accessible) from within the method (PROCEDURE) "TForm1.Button1Click" where it is defined. The variable "access" in TForm3.Button1Click is an entirely different variable (not because it is named differently, but because it is defined as a LOCAL variable in a completely different method). Also, this variable has not been instantiated either, so it is also in an undefined state, which will most likely lead to an access violation there, as well.
You seem to lack some basic understanding on variables, scopes and how to pass values from one method to another, which is beyond the scope of stackoverflow to provide, but here at least is a beginning as to why you get the access violation.
Your class Gazi should look like that:
TGazi = class
private
{ private declarations }
FRektorAdi: String;
function GetRektorAdi: String; //getter
procedure SetRektorAdi(value: String); // setter
public
{ public declarations }
constructor Create;
property RektorAdi: String read GetRektorAdi write SetRektorAdi;
end;
implementation
constructor TGazi.Create;
begin
end;
function TGazi.GetRektorAdi: String;
begin
Result := FRektorAdi;
end;
procedure TGazi.SetRektorAdi(value: String);
begin
if (value <> FRektorAdi) then
FRektorAdi := value;
end;
end.
Then the Unit2 can access its value like that:
procedure TForm1.Button1Click(Sender: TObject);
var newElement: TGazi;
begin
try
newElement := TGazi.Create;
newElement.RektorAdi := 'Pala';
...
Label1.Caption := newElement.RektorAdi;
finally
FreeAndNil(newElement);
end;
end;
outside this event (Button1Click) the class will not be accessible any more, as you have destroyed it in the end. So Unit3 can not get the actual value 'Pala'.
Highlight
This constructor:
constructor TCoords.Create(const AX, AY: Integer);
begin
TCoords.Create(Point(AX, AY));
end;
has been confirmed malfunctioning in both Linux Lazarus 2 and Windows Delphi XE6.
Could this be a bug?
I am new to OOP in Lazarus / Delphi, excuse possible newbie error. Thank you.
I can't seem to understand why the following sequence of Lazarus / (Delphi-like) custom, very basic, an object will not work. I'm trying to debug this for hours already, since then I found:
What works:
Calling the one constructor without an argument, and calling the one with TPoint argument directly.
What doesn't:
Calling this one:
constructor Create(const AX, AY: Integer);
However, I found this would work - But only if if called without its class name inside the constructor. Why is that causing trouble?
Declarations
// WORKS - this creates instance of TCoords initialized to PointOutOfReach
constructor Create; reintroduce;
// WORKS - this creates instance of TCoords initialized to user coordinates
constructor Create(const ACoords: TPoint);
// DOES NOT WORK, strangely returns Point(0, 0), if called with class name
// WORKS only if called without class name - confusing or error on my side?
constructor Create(const AX, AY: Integer);
Calls
// OK - WORKING
NewCoords := TCoords.Create;
NewCoords.X:=12;
NewCoords.Y:=120;
ShowMessage(NewCoords.X.ToString + ' : ' + NewCoords.Y.ToString);
NewCoords.Free;
// OK - WORKING
NewCoords := TCoords.Create(Point(12, 120));
ShowMessage(NewCoords.X.ToString + ' : ' + NewCoords.Y.ToString);
NewCoords.Free;
// NOT WORKING as expected
NewCoords := TCoords.Create(12, 120);
ShowMessage(NewCoords.X.ToString + ' : ' + NewCoords.Y.ToString);
NewCoords.Free;
Coords unit with TCoords object definition
unit Coords;
{$mode objfpc}{$H+}
interface
uses
Classes;
type
// Flexible X,Y coordinates object.
TCoords = class(TObject)
// these declarations are accessible within this unit only
private
// this is the variable we are working with
FCoords: TPoint;
// property for this function is unnecessary, but I like it as it is
function IsInitialized: Boolean;
// these declarations are accessible to all
public
// this creates instance of TCoords initialized to PointOutOfReach
constructor Create; reintroduce;
// this creates instance of TCoords initialized to user coordinates
constructor Create(const ACoords: TPoint);
// THIS ONE DOES NOT WORK, strangely returns Point(0, 0)
constructor Create(const AX, AY: Integer);
// this indicates if instance was initialized or not by the user
property Initialized: Boolean read IsInitialized;
// this works directly with private FCoords variable storing coordinates
property P: TPoint read FCoords write FCoords;
// these two are shortcuts for X,Y coordinates' direct access
property X: Integer read FCoords.X write FCoords.X;
property Y: Integer read FCoords.Y write FCoords.Y;
end;
implementation
var
// this gets initialized when loading this unit
PointOutOfReach: TPoint;
constructor TCoords.Create;
begin
// this is the same as `inherited`, but I like to be explicit
inherited Create;
// since called without argument, we have to ensure, there is some nonsense
FCoords := PointOutOfReach;
end;
constructor TCoords.Create(const ACoords: TPoint);
begin
// this is the same as `Create`, but I like to be explicit
TCoords.Create;
// in the previous mandatory call we have initialized FCoords already
// but to PointOutOfReach; here we overwrite it with user coordinates
FCoords := ACoords;
end;
constructor TCoords.Create(const AX, AY: Integer);
begin
// this is the same as `Create(TPoint)`, but I like to be explicit
// TCoords.Create(Point(AX, AY));
// Why can't I call the above, shouldn't it be the very same?
Create(Point(AX, AY));
end;
function TCoords.IsInitialized: Boolean;
begin
// this returns True in case FCoords has been initialized
// initialized means here for the FCoords point to be different from PointOutOfReach
// achieved either by calling `Create(APoint)`, or later overwriting PointOutOfReach
Result := FCoords <> PointOutOfReach;
end;
initialization
// initialize PointOutOfReach to "impossible" coordinates when loading unit
PointOutOfReach := Point(MAXINT, MAXINT);
end.
Thank you in advance, I myself can't seem to see the difference between those two.
Major error corrected - no change
Missing overload; in constructors' declarations has been corrected. Still getting 0,0 coords from the last constructor, sadly.
David Heffernan stated the reason for my approach not to work in a comment, let me quote:
TCoords.Create(Point(AX, AY)) creates a new instance. When you do this inside a constructor you now have two instances. Replace it with Create(Point(AX, AY)).
Thank you kindly for the explanation!
If even solved, I think a better approach will be not chaining those constructors.
Applying this rule works, working snippet with unchained constructors:
constructor TCoords.Create;
begin
inherited Create;
// since called without argument, we have to ensure,
// there are some corner-case coordinates, so that we can
// differentiate between a [0:0] and uninitialized state
FCoords := PointOutOfReach;
end;
constructor TCoords.Create(const ACoords: TPoint);
begin
inherited Create;
FCoords := ACoords;
end;
constructor TCoords.Create(const AX, AY: Integer);
begin
inherited Create;
FCoords := Point(AX, AY);
end;
PS: For the code to work, so far I see no need to apply "setters" as in Nasreddine Galfout's answer.
It is the way you are declaring the properties X and Y change them to this
property X: Integer read FCoords.X write SetCoordX;
property Y: Integer read FCoords.Y write SetCoordY;
procedure TCoords.SetCoordX(const Value: Integer);
begin
FCoords.X := Value;
end;
procedure TCoords.SetCoordY(const Value: Integer);
begin
FCoords.Y := Value;
end;
This has to do with how Delphi does assignment of properties. In your case you are assigning to an implicit variable added by the compiler when retrieving the value of X.
I can't seem to remember where I read about this I will find it and edit my answer
How can I change (If possible) a value in a class, whilst inside another class procedure. Example:
Class1 : Class
Private
Random : Integer;
public
end;
Class2 : Class
Private
Public
Procedure DoSomething();
end;
Procedure Class2.DoSomething();
Begin
//Do Something
If ... then
Change Random to ...
end;
It depends. You first have to think of the reason why the visibility is separated. private methods are intended for use within a class, while public methods are intended for use outside of a class.
In your particular example, you are not referencing a class. Instead, I will use your example to demonstrate the following:
type
TMyObject = class(TObject)
private
FNumber: Integer;
function GetNumber: Integer;
procedure SetNumber(Input: Integer)
public
property Number: Integer read GetNumber write SetNumber;
end;
function TMyObject.GetNumber: Integer;
begin
Result := FNumber;
end;
procedure TMyObject.SetNumber(Input: Integer);
begin
FNumber := Input;
end;
As you can see, I've added a property called Number which uses GetNumber to obtain the value and SetNumber to assign it. Use of such methods is almost always coupled with the use of a property in this manner.
Coming back to your original question, as I said, it depends. Your property setter might perform some additional code than just assigning the value, for example. In such a case, from within your class, you may need to set this value through its private FNumber field instead, so that the additional setter code isn't called.
So in short, the answer is no. It is not absolutely necessary to access private members through getters and setters from within the class. However, from outside the class, then yes, it will be necessary.
On the other hand, you could also declare the member under strict private, which would force the class member to only be visible from within the class itself, and not from anywhere else in the same unit.
Read more here about visibility of class members.
strict private and strict protected
declarationsection were introduced in D2007. Members declared in a
strict private section are not accessible from other classes even in the
same unit, as this example shows:
type
TMyClass = class
private
MyPrivateField : Integer;
strict private
MyStrictPrivateField : Integer;
public
end;
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
end;
procedure TForm1.FormCreate(Sender: TObject);
var
MyClass : TMyClass;
begin
MyClass := TMyClass.Create;
MyClass.MyPrivateField := 0; // compiles ok
MyClass.MyStrictPrivateField := 1; // does not compile
// fails with E2361, "Cannot access private symbol TMyClass.MyStrictPrivateField
end;
Note that not only does this fail to compile, but in Seattle at least,
MyStrictPrivateField does not show up in the autocomplete list for
TMyClass (with the insertion point in FormCreate), unlike MyPrivateField,
which does.
So lots of languages have a pattern where you do something like this:
object = Create_Object().Set(1).Set(2).Set(3);
(I believe this originated in Smalltalk.) This works because the Set() method returns a reference to its receiver.
Can I do anything like this in Ada?
Approaches I've tried which don't work include:
-- doesn't work because the returned object is a read-only copy of the receiver
function Set(self: in out Object) return Object;
-- doesn't work because I can't return an access to a local variable
function Set(self: in out Object) return access Object;
-- looks like it works until I realise that it's not a method, and isn't doing
-- dynamic dispatch [*]
function Set(self: access Object) return access Object;
Can this be done?
I think a function with this profile will do the job for you:
function Set (Target : in Instance;
New_Item : in Integer) return Instance;
Having written a full package around that function declaration, I can write:
Object := Set (1).Set (2).Set (3);
Object.Show;
and get the output:
{1, 2, 3}
I've pushed the full sources to http://repositories.jacob-sparre.dk/miscellaneous-ada-2005-examples/.
Your third proposal is the correct approach, and you are in fact defining a primitive operation when you type "access" for the parameter. Here is an example, which uses two tagged types to show where dispatching occurs, and uses chaining of method calls. I have provided a procedure for convenience, as well, since otherwise you would have to use a temporary variable. I have used Create_Object, but an explicit call to "new", but that's of course the same thing. In addition, I have shown an example where Ada will not do dynamic dispatching when it knows statically the types involved. This is actually a nice features (performance-wise), even if indeed it requires care (and even experts are bitten every now and then :=)
with Utils; use Utils;
procedure Chain is
O : access Object := new Object;
C : access Child := new Child;
begin
O.Add (1).Add (2);
C.Add (3).Add (4);
end Chain;
package Utils is
type Object is tagged null record;
function Add (Self : access Object; Val : Integer) return access Object;
procedure Add (Self : access Object; Val : Integer); -- for convenience
type Child is new Object with null record;
overriding function Add (Self : access Child; Val : Integer) return access Child;
overriding procedure Add (Self : access Child; Val : Integer); -- for convenience
end Utils;
with Ada.Text_IO; use Ada.Text_IO;
package body Utils is
function Add (Self : access Object; Val : Integer) return access Object is
begin
Put_Line ("func Object.Add" & Val'Img);
Self.Add (Val); -- static call, not dynamic dispatch
return Self;
end Add;
procedure Add (Self : access Object; Val : Integer) is
begin
Put_Line ("proc Object.add" & Val'Img);
end Add;
overriding function Add (Self : access Child; Val : Integer) return access Child is
begin
Put_Line ("Child.Add" & Val'Img);
Self.Add (Val); -- static call, not dynamic dispatch
return Self;
end Add;
overriding procedure Add (Self : access Child; Val : Integer) is
begin
Put_Line ("proc Child.Add" & Val'Img);
end Add;
end Utils;
The output of this program is:
func Object.Add 1
proc Object.add 1
proc Object.add 2
Child.Add 3
proc Child.Add 3
proc Child.Add 4
Edit: As discussed in the comments, it is recommended to always use overriding to make sure the procedure is indeed overriding, not using a different profile. An access parameter does create a primitive operation.
From paragraph 18, function [formal] parameters can only use mode 'in' (read-only). So the input object does not get modified.
18 {parameter mode} The parameter mode of a formal parameter conveys the direction of information transfer with the actual parameter: in, in out, or out. Mode in is the default, and is the mode of a parameter defined by an access_definition. The formal parameters of a function, if any, shall have the mode in. [Ada 2005]
So I do not think that the language supports it as shown in other languages.
However, if you don't mind copies, we can save the result back in the object, but that's not the same as those other languages that you reference.
obj := obj.set("this").set(123).set(some_other_type);
You set "this" on a copy of 'obj' and return that copy. From that copy, we create a new copy and set 123 in that copy, which is in turn returned. Finally, that last result is copied and we set 'some_other_type' to it. That last copy is returned and we can save it in obj. Note that a well optimized implementation can avoid most if not all of those copies if the set() functions are small enough and inlined, but I would not could on it.
In retrospect, using procedures:
obj.set("this");
obj.set(123);
obj.set(some_other_type);
will do no copies at all.