Before diving into the various callbacks, we shall learn the simple but very powerful inheritance rules. We use the parents of a given path for this. For example, the parents of node/%/view are:
node/%
node

If a page callback is not defined for a path, then we look at the closest parent that has one and use it. If the page callback is inherited from a parent, then the page arguments, the file and the file path are inherited from the parent as a whole, but can be overridden. Most of the time it is only required to overwrite the page arguments and nothing else.

If the page callback is defined for a given path, then nothing is inherited and the page arguments, file, and file path must be defined if they are required.

For example:

  $items['admin/user/roles'] = array(
    'title' => 'Roles',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('user_admin_new_role'),
    'file' => 'user.admin.inc'
  );
  $items['admin/user/roles/edit'] = array(
    'title' => 'Edit role',
    'page arguments' => array('user_admin_role'),
  );

The above is shorthand for:

  $items['admin/user/roles'] = array(
    'title' => 'Roles',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('user_admin_new_role'),
    'file' => 'user.admin.inc'
  );
  $items['admin/user/roles/edit'] = array(
    'title' => 'Edit role',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('user_admin_role'),
    'file' => 'user.admin.inc',
  );

Note that the 'page callback' and the 'file' are inherited from the parent while the 'page arguments' is defined (overridden) for this path.

The following

  $items['admin/user/roles/edit'] = array(
    'title' => 'Edit role',
  );

is shorthand for

  $items['admin/user/roles/edit'] = array(
    'title' => 'Edit role',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('user_admin_new_role'),
    'file' => 'user.admin.inc',
  );

In this case the callback, the arguments and the file are inherited.

  $items['admin/user/rules'] = array(
    'title' => 'Access rules',
    'page callback' => 'user_admin_access',
    'file' => 'user.admin.inc',
  );
  $items['admin/user/rules/edit'] = array(
    'title' => 'Edit rule',
    'page callback' => 'user_admin_access_edit',
    'file' => 'user.admin.inc',
  );

In this case there is no inheritance because a 'page callback' is defined for the 'admin/user/rules/edit' path. So if the 'page arguments', 'file', and 'file path' are required, they must be defined in the menu item definition.

Inheritance for access callbacks was supported the same way as with page callbacks before Drupal 6.2. Since Drupal 6.2 however, access callbacks are only inherited for default local tasks (neither the callback nor the arguments).

In the general case (i.e. all cases except default local tasks), if neither 'access callback' nor 'access arguments' is set then access will be denied (the 'access callback' will be set to 0). If 'access callback' is not set but 'access arguments' is then http://api.drupal.org/api/function/user_access/6 will be used as the 'access callback'. I.e., you don't have to provide the access callback on all menu items - only on those that need to use something other than the default user_access(). If 'access callback' is set but 'access arguments' is not then 'access arguments' defaults to the empty array.

To see how inheritance is built check the implementation of _menu_router_build

It's worth noting that when menu items define page callbacks, this disables inheritance, and it also disables any nesting that you might expect based on paths. In the last example above, the two menu items 'Access rules' (admin/user/rules) and 'Edit rule' (admin/user/rules/edit) will be peers in the Navigation menu, rather than one being nested under the other (as might be expected).