Let me give it a try.
Let's say you have class Print that contains members functions a, b, and c. If you have an object of type "Print", you can call those functions with the syntax p.a(), p.b(), p.c(), etc. So far so good?
Let's further say, without going into detail, that you have another class LiquidCrystal that inherits from class Print. That means, roughly, that every LiquidCrystal object is [u]also[/u] a Print object. So a LiquidCrystal object can call Print member functions a, b, and c in addition to whatever functions are defined in LiquidCrystal.
That's why you can write lcd.print(), even though the LiquidCrystal class doesn't (directly) provide a print() method. It's provided by Print!
The magic in this particular design is that the Print class's print() (eventually) calls the mysterious "write" function to "write" a byte. But wait a second! Print doesn't have a "write" function. Where does "write" get defined?! Answer: back down in the LiquidCrystal class.
Just as LiquidCrystal relies on Print to provide the print() function, Print relies on LiquidCrystal to provide the write() function. LiquidCrystal's "write" function is where all the smarts about how to write to an LCD live.
All the other classes that derive from Print provide a write() function too. That's why
lcd.print() -> prints to an LCD (LiquidCrystal)
Serial.print() -> prints to a serial port (HardwareSerial)
nss.print() -> prints to a software serial port (NewSoftSerial)
eth.print() -> prints to an ethernet port (Ethernet)
str.print() -> prints to a string (PString)