-1

For Delphi 10.2.3: Not sure how to ask this question, but how do I create a method similar to memo1.lines.add(); and memo1.Lines.Count.ToString; where lines contains many other methods, procedures, and properties??

This is how I think it maybe:

unit.someproperty.anotherproperty.mymethod(myvariable: variabletype): variabletype;

or

unit.someproperty.unit2.mymethod(myvariable: variabletype): variabletype;

Appearance would appear like:

function component.extract.tagA(attribute, source: string): string;
procedure component.insert.tagA(attribute, source, dest: string);
procedure component.modify.tagA(attribute, source, dest: string);

if you type component. it would give you help with extract, insert, and modify as options to use next.

So, how do i make a function or procedure where I can have .extract. or .extract. or .insert. ETC

I know this should probably be basic knowledge, but the project I'm working on is becoming big enough for me to make it easier to read and use. I know this can be done, but I don't know how to word it properly in order to find what I need to do this.

I want to have multiple units... then I create a component using them so they have nested methods and procedures that work like those DOTTED methods and procedures you see in Tmemo... like memo1.lines.add, memo1.lines.delete, memo1.lines.insert, etc.

Please help! Thanks in advance!

El Diablo
  • 168
  • 1
  • 12
  • Ignore the memo.lines, or whatever I wrote... for some reason your just reading those words and not really seeing what I'm trying to do. I'm trying to understand how to create nested methods / procedures... but not nested inside procedures / methods. When I look up nested procedures in google, i get many examples how to nest inside the procedure, but nothing on showing me how to create a component that has multiple DOTS between words to create a method or procedure! unit.someproperty.anotherproperty.mymethod(myvariable: variabletype): variabletype; <<-- create that – El Diablo Jan 04 '19 at 17:50

2 Answers2

3

Delphi syntax does not permit you to declare a class to have dotted sub-properties.

However, you can achieve the effect of this by using a style of coding known as fluent design (see https://en.wikipedia.org/wiki/Fluent_interface). Here is an ultra-simple example:

type
  TMySubProperty = class
    protected
    procedure DoSomething;
    property Width : Integer read {define getter and setter}
  end;

  TMyComponent = class(TComponent)
  [...]
  property
    MySubProperty : TMySubProperty read GetMySubProperty;
  end;

  [...]

  function TMyComponent.GetMySubProperty : TMySubProperty;
  begin
    Result := {calculate the result however you like}
  end;

Then, in your code you can write things like

  MyComponent.MySubProperty.Width := 666;
  MyComponent.MySubProperty.DoSomething;

Obviously you can have any number of sub-properties and they can be nested to any arbitrary level: basically, you need a class type for the sub-property and a function in the owning class (TMyComponent in this simple example) which returns the class instance you are trying to access. The Getter Functions can be coded to accept parameters which identify a specific instance of the sub-property class, as in

  MyComponent.MySubProperty[i].Width := 666;

That should be enough to get you going, if not ask.

MartynA
  • 30,454
  • 4
  • 32
  • 73
  • This answers my question. – El Diablo Jan 04 '19 at 21:49
  • Good, I'm glad. Perhaps you would be so kind as to accept it, then. – MartynA Jan 04 '19 at 21:58
  • How do I accept it? I however up voted it. Never-mind found it... I have to click on the check just below the voting buttons. – El Diablo Jan 04 '19 at 22:01
  • At the top-tleft of the answer is a kind of "Tick" icon. Just click it ... – MartynA Jan 04 '19 at 22:03
  • 1
    @MartynA Just for the record, your example (while it may be what OP was looking for) has nothing to do with Fluent Interfaces. Main feature of fluent interface is ability to chain method (function) calls without explicitly referencing instance again achieved by returning Self from each call. As example (if you disregard inheritance part of the question, that commonly doesn't mix well with fluent) you can look at [Fluent Interface in Delphi](https://stackoverflow.com/questions/28125514/fluent-interface-with-inheritance-in-delphi) – Dalija Prasnikar Jan 05 '19 at 11:27
  • Yeah, you should really delete the fluid interface reference, as it is not what is happening here and therefore misleading. – Sherlock70 Jan 07 '19 at 13:38
2

What you are looking for is nested objects. Memo1 is an instance of the TMemo class, which has a Lines property that is an instance of the TStrings class, which has methods like Add(), Delete(), Insert(), etc and properties like Count, etc.

So, in your component, it would need nested objects for extract, insert, and modify, and those objects would need to be instances of types that have a tagA() method.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 1
    This also explains what I'm looking for, but I see you have no example on how. MartynA shares an example on how I can hopefully achieve it fluent design. I'm going to go and try to code it now. Remy, do you have a different example for what your explaining or is it the same? – El Diablo Jan 04 '19 at 21:56
  • I Think what's Remy wants to say is You should understand, that U can have an object as property/class field of another object... – Vancalar Jan 04 '19 at 23:05
  • http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Fields_(Delphi) – Vancalar Jan 04 '19 at 23:12