I could tell you straight away how the relation is implemented, but let me show you how you can find the answer by yourself.
Open VendTable table in the designer. Put address to the search box above, which means that only fields and methods containing "address" in their names will be shown. postalAddress() method looks promising, therefore open it. You'll see this code:
LogisticsPostalAddress postalAddress()
{
return DirParty::primaryPostalAddress(this.Party);
}
As you see, the Party field is crucial here. There is a generic concept of a party (customer, vendor, worker, legal entity...) and addresses are linked to parties, not the specific role of a party (such as a vendor).
Now look into primaryPostalAddress():
server static LogisticsPostalAddress primaryPostalAddress(
DirPartyRecId _partyRecId,
TransDateTime _transDateTime = DateTimeUtil::utcNow())
{
LogisticsPostalAddress postalAddress;
DirPartyLocation partyLocation;
select firstonly postalAddress
exists join partyLocation
where partyLocation.Location == postalAddress.Location
&& partyLocation.IsPrimary == true
&& partyLocation.Party == _partyRecId;
return postalAddress;
}
This gives you the remaining details. There is another generic concept of a location, which we don't need to worry about too much here. We see that a party is linked to a location via DirPartyLocation table, and we can directly join this table with LogisticsPostalAddress.
Note that a party can have more than one address. This method gives you the primary one, which is usually what you want if you don't have any specific requirements.
Regarding contact details, do the same excercise for phone() method, for example.