How closely, in general, should programming objects mirror real-life objects.
Not much, only enough.
One of the main characteristics of OOP, is abstraction. You don't need to have all the attributes/methods of an object to be able to use it.
You just need to the basic to use it.
The whole thing about objects, is to have the data and the functions that perform something about that data in the same place.
So in your fruit class I would better have something as Color
or an indication if it would be eaten. For instance:
Fruit
+ color : Color
- isMature : Boolean
+ canBeEaten() : Boolean
return isMature
That way you may create different fruits
apple = Fruit()
appe.color = Color.red
out.print( "Can this fruit be eaten? %s ", apple.canBeEaten() )
orange = Fruit()
orage.color = Color.orange
out.print( "Can this fruit be eaten? %s ", orange.canBeEaten() )
Etc.
If you see the attributes ( color and isMature ) are stored inside the object. That way you don't have to keep track of their state from outside.
As for inheritance, it only makes sense when you need to add a new behaviour to some method, and yes, the methods are relative to the attributes or characteristics of the object. As you point out fruit.eat()
doesn't make much sense.
But consider a method to get the Juice from the fruit.
Fruit
+ getJuice(): Juice
Apple -> Fruit
+ getJuice(): Juice
// do what ever is needed internally to create the juice
Orange -> Fruit
+ getJuice(): Juice
// here, certainly the way to get the juice will be different