Stop thinking in terms of addresses and public keys. In bitcoin we are "locking" up coins inside "smart contracts" and to spend those coins you need to provide an "unlocking mechanism/script" to be able to spend them.
It could be described as locked mailboxes. If you know the address of the mailbox you can go to it and insert the mail into its opening slot. But only the owner who has the key can open the lid and take the contents out.
In Bitcoin the "key" that unlocks your coins to allow you to spend them or the "unlocking mechanism" is a script in the Bitcoin's smart contract protocol.
For example take this very simple example: 3MaB7QVq3k4pQx3BhsvEADgzQonLSBwMdj
Coins sent to this address can be spent by providing a very simple unlocking script that only contains OP_TRUE.
<0x51> +
OP_HASH160 da1745e9b549bd0bfa1a569971c77eba30cd5a4b OP_EQUALAs you can see there is no public key here.
It's the same with everything else like when you send coins to a P2PKH address you are locking coins inside a
OP_DUP OP_HASH160 <push20> OP_EQUALVERIFY OP_CHECKSIG smart contract. To unlock this the owner has to provide a script like
<push72><push33> containing ECDSA signature and public key.
To verify the validity of these scripts, the nodes evaluate and execute these scripts in a
FORTH like script language and if it ends up with a success, the transaction is valid and coins can be spent.