Object oriented programming - class design confusi

2019-03-19 05:19发布

I am trying to wrap my head around object oriented programming.

My understanding is that we have objects so we can design our programs to mirror real-life objects.

Let's take a class hierarchy:

class Fruit {
    void Eat() {

    }
}

class Apple extends Fruit {

}

Obviously, you can use Fruit polymorphically if Eat() is virtual. But does this make sense? Fruit cannot eat itself!

Should a fruit object rather be passed to a human object which has a Eat() function?

I am trying to figure out the correct way to think about this. How closely, in general, should programming objects mirror real-life objects?

13条回答
别忘想泡老子
2楼-- · 2019-03-19 05:27

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
查看更多
走好不送
3楼-- · 2019-03-19 05:29

Should a fruit object rather be passed to a human object which has a Eat() function?

Yes.

But program objects are generally more abstract than this naive example. In the real world of computer programming, objects like fruit and humans would generally be represented as attributes in a database. The consumption and manipulation of such data would be done in programming objects.

查看更多
走好不送
4楼-- · 2019-03-19 05:30

I tend to think about:

Is a

Has a

So, an apple is a fruit, so inheritance makes sense.

But, fruit has (is) eatable may make sense, but that shows it is a property of fruit, not an action (method).

For example, you may have unripened apple, that would not be edible (eatable) so you could then set this property.

Now, whatever is going to eat this you could set whether an apple is part of it's diet.

Now Has a would be for composition. So, an apple has a seed would mean that seed doesn't extend apple, but an apple would have a collection of seeds.

So, you do have a design problem, and I hope that these two concepts may help to clarify.

查看更多
太酷不给撩
5楼-- · 2019-03-19 05:36

Simply mirroring real-world objects is rarely a good idea. To borrow from a classic example - software that controls a coffeemaker is not about coffee beans and hot water - it's about making coffee.

You need to find the underlying abstraction to your real-world problem, not just copy nouns into object hierarchies.

If your apple derives from fruit, does it add any interesting behavior? Is the hierarchy really needed? Inheritance adds a level of complexity to your software and anything increasing complexity is bad. Your software is just a bit harder to follow and understand, there's just a bit more to cover in your test and the likelihood of a bug is just a tiny bit larger.

I find OOP is more about the whitespace - what you are leaving out is more important.

查看更多
姐就是有狂的资本
6楼-- · 2019-03-19 05:44

Something of class Herbivore would have an Eat function, as would something of class Carnivore, but each one's Eat would have some differing restrictions on what argument could be passed to the Eat function. The Fruit is what is eaten, so it would be passed as the argument to Herbivore.Eat(), whereas you would want to pass an object of type Hamburger to Carnivore.Eat(), and raise an exception if Hamburger were passed to Herbivore.Eat().

But really, I don't think OOP is so we can model software objects to be just like real-life objects. I've found that most of my OOP design works with pretty abstract objects, and only with respect to the system they are part of. If I wrote a library checkin/checkout system, I would model a Book in terms of its administrative properties and functions - I would not model it as a collection of Page objects, and I doubt I would even define anything like a Read() method, although such is the main purpose of having a book in the first place. The Book object's role in the system dictates my design much more than what one does with books in the real world.

查看更多
仙女界的扛把子
7楼-- · 2019-03-19 05:44

My understanding is that we have objects so we can design our programs to mirror real-life objects.

Maybe more like 'relate' them to real life objects, where applicable.

Should a fruit object rather be passed to a human object which has a Eat() function?

Yes, or something more general than a human.

I am trying to figure out the correct way to think about this. How closely, in general, should programming objects mirror real-life objects.

Only define what you need to define. Then the implementation (typically) becomes very obvious. In other words, you're probably thinking too hard.

查看更多
登录 后发表回答