Chapter 35
Creating methods

Component methods are procedures and functions built into the structure of a class. Although there are essentially no restrictions on what you can do with the methods of a component, Delphi does use some standards you should follow. These guidelines include

In general, components should not contain many methods and you should minimize the number of methods that an application needs to call. The features you might be inclined to implement as methods are often better encapsulated into properties. Properties provide an interface that suits the Delphi environment and are accessible at design time.

Avoiding dependencies

At all times when writing components, minimize the preconditions imposed on the developer. To the greatest extent possible, developers should be able to do anything they want to a component, whenever they want to do it. There will be times when you cannot accommodate that, but your goal should be to come as close as possible.

This list gives you an idea of the kinds of dependencies to avoid:

The best way to handle these situations is to ensure that you provide ways out of them. For example, if calling a method puts your component into a state where calling another method might be invalid, then write that second method so that if an application calls it when the component is in a bad state, the method corrects the state before executing its main code. At a minimum, you should raise an exception in cases when a user calls a method that is invalid.

In other words, if you create a situation where parts of your code depend on each other, the burden should be on you to be sure that using the code in incorrect ways does not cause problems. A warning message, for example, is preferable to a system failure if the user does not accommodate your dependencies.

Naming methods

Delphi imposes no restrictions on what you name methods or their parameters. There are a few conventions that make methods easier for application developers, however. Keep in mind that the nature of a component architecture dictates that many different kinds of people might use your components.

If you are accustomed to writing code that only you or a small group of programmers use, you might not think too much about how you name things. It is a good idea to make your method names clear because people unfamiliar with your code (and even unfamiliar with coding) might have to use your components.

Here are some suggestions for making clear method names:

As a final consideration, make sure the method really needs to be a method. A good guideline is that method names have verbs in them. If you find that you create a lot of methods that do not have verbs in their names, consider whether those methods ought to be properties.

Protecting methods

All parts of classes, including fields, methods, and properties, have a level of protection or "visibility," as explained in "Controlling access". Choosing the appropriate visibility for a method is simple.

Most methods you write in your components are public or protected. You rarely need to make a method private, unless it is truly specific to that type of component, to the point that even derived components should not have access to it.

Methods that should be public

Any method that application developers need to call must be declared as public. Keep in mind that most method calls occur in event handlers, so methods should avoid tying up system resources or putting Windows in a state where it cannot respond to the user.

Note: Constructors and destructors should always be public.

Methods that should be protected

Any implementation methods for the component should be protected so that applications cannot call them at the wrong time. If you have methods that application code should not call, but that are called in derived classes, declare them as protected.

For example, suppose you have a method that relies on having certain data set up for it beforehand. If you make that method public, there is a chance that applications will call it before setting up the data. On the other hand, by making it protected, you ensure that applications cannot call it directly. You can then set up other, public methods that ensure that data setup occurs before calling the protected method.

Property-implementation methods should be declared as virtual protected methods. Methods that are so declared allow the application developers to override the property implementation, either augmenting its functionality or replacing it completely. Such properties are fully polymorphic. Keeping access methods protected ensures that developers do not accidentally call them, inadvertently modifying a property.

Abstract methods

Sometimes a method is declared as abstract in a Delphi component. In the VCL, abstract methods usually occur in classes whose names begin with "custom", such as TCustomGrid. Such classes are themselves abstract, in the sense that they are intended only for deriving descendent classes.

While you can create an instance object of a class that contains an abstract member, it is not recommended. Calling the abstract member leads to an EAbstractError exception.

The abstract directive is used to indicate parts of classes that should be surfaced and defined in descendent components; it forces Component writers to redeclare the abstract member in descendent classes before actual instances of the class can be created.

Making methods virtual

You make methods virtual when you want different types to be able to execute different code in response to the same method call.

If you create components intended to be used directly by application developers, you can probably make all your methods nonvirtual. On the other hand, if you create abstract components from which other components will be derived, consider making the added methods virtual. This way, derived components can override the inherited virtual methods.

Declaring methods

Declaring a method in a component is the same as declaring any class method.

To declare a new method in a component, you do two things:

The following code shows a component that defines two new methods, one protected static method and one public virtual method.

type
  TSampleComponent = class(TControl)
  protected
    procedure MakeBigger;                              { declare protected static method }

  public
    function CalculateArea: Integer; virtual;            { declare public virtual method }
  end;
...

implementation
...
procedure TSampleComponent.MakeBigger;                          { implement first method }
begin
  Height := Height + 5;
  Width := Width + 5;
end;

function TSampleComponent.CalculateArea: Integer;              { implement second method }
begin
  Result := Width * Height;
end;