views:

223

answers:

3

Hello, stackoverflowers :)

As much I know - Subroutines are with Private access mode to its parent unction / procedure, right?

Is there any way to access them from "outer-world" - dpr or other function / procedure in unit?

Also - which way takes more calcualtion and space to compiled file?

for example:

function blablabla(parameter : tparameter) : abcde;
 procedure xyz(par_ : tpar_);
 begin
  // ...
 end;
begin
 // ...
end;

procedure albalbalb(param : tparam) : www;
begin
 xyz(par_ : tpar_); // is there any way to make this function public / published to access it therefore enabling to call it this way?
end;

// all text is random.

// also, is there way to call it from DPR in this manner?

// in C++ this can be done by specifing access mode and/or using "Friend" class .. but in DELPHI?
+2  A: 

No, there is no way to do what you're asking. The xyz function is callable only by the enclosing blablabla function. Outside that function, xyz is not in scope and there is no way to name it. If C++ allowed nested function, there wouldn't be any way to refer to it, either, just like there's no way to refer to functions with static linkage from outside the current translation unit.

If you need to call xyz from outside the blablabla function, then move xyz outside. If you need to call it from outside the current unit, then you need to declare that function in the unit's interface section. Then, add that unit to the external code's uses clause and you can call xyz from wherever you want, even the DPR file.

If xyz refers to variables or parameters of the blablabla function, then you'll need to pass them in as parameters since xyz will no longer have access to them otherwise.

The concept of access specifiers isn't really relevant here since we're not talking about classes. Units have interface and implementation sections, which aren't really the same as public and private sections of a class.

Rob Kennedy
+4  A: 

Note: Embedded Routines <> Private/Protected Methods.

Embedded routines i.e. routines inside routines can not be accessed by external routines. You have posted an example of an Embedded routine, I also heard them called Internal Routines.

Here is another example:

procedure DoThis;

function DoThat : Boolean;
begin
  // This Routine is embedded or internal routine.
end;
begin

// DoThat() can only be accessed from here no other place.

end;

Regardless of visibility, methods on classes, can be called using Delphi 2010 via RTTI. I have detailed how to do this in this article.

If you are in the same Unit methods on a class can be accessed by any other code regardless of visibility, unless they are marked with Strict Private. This Question has more details and good example code in the accepted answer.

If you are in two different units you can use the Protected Method Hack to access the protected methods. Which is detailed in detailed in this article.

Robert Love
+6  A: 

Nested procedures/functions - those declared inside another procedure or function, are a special type, because they can access the stack (and thereby parameters/local variables) of the procedure they are nested in. Because of this, and Delphi scope rules, there is no way to access them outside the "parent" procedure. You use them only if you need to take advantage of their special features. AFAIK Delphi/Pascal is one of the few languages to have this feature. From a compiler point of view the call has some extra code to allow accessing the parent stack frame, IIRC. AFAIK "friend" class/functions in C++ are different - they are class access methods, while in your example you are using plain procedures/functions. In Delphi all procedure/classes declared in the same unit are automatically "friend", unless strict private declarations are used in latest Delphi releases. For example this code snippets will work, as long everything is in the same unit:

  type
    TExample = class
    private
      procedure HelloWorld;
    public
    ...
    end;

  implementation

    function DoSomething(AExample: TExample);
    begin
      // Calling a private method here works
      AExample.HelloWordl;
    end;
ldsandon