The recommended method would be employing abstract contract (or interface) definition in solidity code (see Service.sol) and the address of the deployed contract implementing it.
Example
Deployed Service.sol:
pragma solidity ^0.4.11;
contract Service{
function isAlive() public constant returns(bool alive) {
// do something
return true;
}
}
Let's assume the deployed contract is deployed at 0x123...
(see serviceAddress below).
Now we want to describe a contract that will use it for something. We'll describe the abstract contract only, so the client knows how to communicate. Then we'll pass in the address so it knows what to communicate with.
Client.sol
pragma solidity ^0.4.11;
// describe the interface
contract Service{
function isAlive() constant returns(bool alive) {} // empty because we're not concerned with internal details
}
contract Client {
Service _s; // "Service" is a Type and the compiler can "see" it because this is one file.
function Client(address serviceAddress) {
_s = Service(serviceAddress); // _s will be the "Service" located at serviceAddress
}
function Ping() public constant returns(bool response) {
return _s.isAlive(); // message/response to Service is intuitive
}
}
Calling deployed contract by ABI and address is similar to a reflection call (expensive) with the limitation that the only output from the call is a boolean return value designating success (true) or an exception (false).