POV-Ray : Newsgroups : povray.general : 4.0 Feature discussion : Re: 4.0 Feature discussion (long) Server Time
9 Aug 2024 15:23:17 EDT (-0400)
  Re: 4.0 Feature discussion (long)  
From: Warp
Date: 2 Oct 2000 09:25:47
Message: <39d88cda@news.povray.org>
Greg M. Johnson <gre### [at] my-dejanewscom> wrote:
: Actually, I think my blobmon character is object-oriented, in the way I've
: broken down INC's to handle different tasks. One has just raw data, another
: computes how raw data variables crunch each other, another poses the model.  A
: POV file would then include the INC and have a walking figure...

  That's modular programming. You split the bigger task into smaller more or
less independent tasks.
  Yes, modularity is an essential part of OO programming, but whether simple
modularity can be considered OO in itself or not is not clear.

  As far as I have understood it, the splitting of a bigger task into smaller
ones (by dividing it into functions, macros, include files or whatever) is
not yet object-oriented programming.

  In OO-programming objects have a declaration (usually called 'class'). This
declaration (class) describes how the object looks like and how it can be
used (ie. it declares an interface). An essential part of this interface
is the so-called information hiding, that is, the implementation of the
class (ie. its data structures and implementation code) is not seen from
the outside and can't be accessed.
  These classes are also called "abstract data types" because they usually
behave exactly like any other data type. For example it could be possible
to make an integer class which behaves exactly like any regular integer
type but may have internally more functionality.

  An instance of this class is called object. An instance is when you create
a physical object which you can handle (part of this creation is allocating
memory for it (often made automatically by the compiler), initializing it
(usually made by the class itself) and so on). There can be many instances
(ie objects) of the same class and they are (usually) independent and
unaware of each other. Each object can have a different state (ie. its internal
values can be anything independently of the other objects of the same class).

  An essential part of OO-design is that often objects have common features
and behaviours.
  For example suppose that you have a class named 'dog' and another named
'cat' and a third called 'tree'.
  The 'dog' and the 'cat' classes will probably have many common functionality
(a functionality which is common to all animals) but different from the
'tree' class. All of them may also have some features common to all living
things (like being alive or dead, etc).
  If a 'dog' can walk and eat, and a 'cat' can also walk and eat, it would
be a bit silly to code the exact same functionality to both (and doing so
would break many modularity principles).
  Sometimes you may also want to handle dogs and cats (and other
animals) in a common way. For example you may have a 'house'-container
with several instances of 'dog' and 'cat' (and perhaps many other
animals) and want to handle all of them in the same way. It would also be
a bit silly to code something like:

if(object is a dog) then make the dog walk, else
if(object is a cat) then make the cat walk, else
...

  It would just be a lot easier (and modular) to say just:

make the animal walk

  This is where inheritance kicks in. Since dogs and cats have common features
(which are common to all animals) and both of them have common features with
the 'tree' (features common to all living things), more abstract classes
could be created.
  We can create an 'animal' class which contains everything that is common
to all animals. Then the 'dog' and 'cat' classes can inherit those features
to itself and then specify some features exclusive to dogs or cats.
  Also we can create a 'plant' class and inherit 'tree' from it.
  Since animals and plants have some common behaviours we can create even a
more abstract class (like 'living_thing' or whatever) and inherit both from
it.
  The inheritance relation between two classes is usually called
"is-a relation", that is, "dog is an animal" and "animal is a living_thing".
Everything that holds for an 'animal' also holds for a 'dog', ie an object
of type 'dog' can be used everywhere an object of type 'animal' is expected.
  It is also possible that some behaviour is common to all animals (eg.
"make noise") but the implementation is specific to each type of animal
(ie. the type of the noise). It is possible to say in the 'animal' class
that all animals make noise but the implementation (which is specific to
each animal) is made in the inherited classes.

  This has several advantages:
  - It structures your data types in a logical way.
  - It's extremely modular. Behaviours that are common to a series of classes
can be written only once instead of having to write it to several places.
  - The abstraction level scheme (thanks to inheritance) gives a lot of
flexibility. It is possible to make, for example, a function that takes
an object of type 'animal' and makes something to it. It doesn't care what
type of animal it is. Then you can give cats and dogs to it and it will work
equally for both. You can also later create new classes inherited from 'animal'
and give them to the function and it will still work without the need of any
modification.
  For example this function could make two things to the 'animal' object:
"walk here" and "make noise". The "walk here" could be independent from
animal to animal and the implementation in the 'animal' class is automatically
called (unless specifically overridden in the inherited class). The "make
noise", however, depends on the type of animal. Still the function doesn't
need to know the type of animal; it just calls the "make noise" functionality
in the 'animal' class and that's it. It doesn't care which implementation is
actually called.
  This feature allows extreme modularity: You can create new types of animals
with their specific way of "making noise" and this function will still work.
You don't have to modify the function to take into account this new animal
type.

  It's important to note the type of the inheritance relation. The relation
is always an is-a relation, ie. from a more abstract concept to a more
concrete concept. It's too usual to misuse this relation.
  The most usual mistake is to use it as if it was a "has-a" relation.
For example, since a 'car' "has a" 'wheel', then we inherit a car from a
wheel.
  This is wrong, of course. A 'car' is NOT a 'wheel'. You can't use a 'car'
where a 'wheel' is expected. A 'wheel' is a part of the 'car', ie. the
car consists of 'wheel' objects (among others).
  The inheritance relation should always be from a more abstract concept
to a more concrete concet. For example it's perfectly normal to think that
a 'car' is a 'vehicle'. An object of type 'car' can be used anywhere an
object of type 'vehicle' is expected.

  This is why in povray splitting a bigger object into smaller objects (which
can possibly be copied more than once to create the bigger object) can't be
called OO-programming. It's modular, but it's not purely object-oriented.
  You can't create abstract concepts in povray and then inherit concrete
concepts from them. You can't for example, create a 'furniture' class
(which is probably so abstract that you can't create an instance, ie an
object from it) and then inherit things like 'table' and 'chair' from it.
You can't create, for example, an array containing 'furniture'-type objects
and add 'tables' and 'chairs' to it (as it is possible in OO-languages).
  Objects in povray don't have clear interfaces either.

-- 
main(i,_){for(_?--i,main(i+2,"FhhQHFIJD|FQTITFN]zRFHhhTBFHhhTBFysdB"[i]
):_;i&&_>1;printf("%s",_-70?_&1?"[]":" ":(_=0,"\n")),_/=2);} /*- Warp -*/


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.