Object-Oriented Programming Problems


Problems you are presented relating to object-oriented programming are likely to focus on the concepts of object orientation, particularly on issues relevant to the languages the company is using in its coding.

Interfaces and Abstract Classes

Important 

Explain the difference between an interface and an abstract class in object-oriented programming.

The specific answer to this depends, of course, on which language you’re developing with, but start the answer by giving some general definitions:

  • An interface declares a set of related methods, outside of any class.

  • An abstract class is an incomplete class definition that declares but does not define all of its methods.

Conceptually, then, an interface defines an application programming interface (API) that is independent of any class hierarchy. In fact, interfaces can be used in non-OO programming models, such as componentbased models like COM and CORBA. However, you’re focusing on the use of interfaces in an object-oriented context, where they are useful in their own right. Interfaces are the ultimate encapsulators, because they hide all the details of the classes that implement their methods from the user of the interface. They’re particularly important - almost necessary, in fact - in languages that only support single inheritance (classes can only inherit from one base class). A class that exposes its members via an interface is said to implement the interface.

Unlike an interface, an abstract class is a proper class: It can have data members and can be a subclass of other classes. Unlike a concrete (nonabstract) class, however, some of its behaviors are deliberately left to be defined by its own subclasses. Abstract classes cannot be instantiated because of this - only instances of concrete subclasses can be created.

An interface is almost identical to an abstract class with no data members and no method definitions. In C++ this is exactly how you’d define an interface: by declaring a class with no data members and only pure virtual functions - something like this, for example:

 class StatusCallback {   public:     virtual void updateStatus( int oState, int nState ) = 0; }

A class could then “implement” the interface by deriving from it:

 class MyClass : SomeOtherClass, StatusCallback {   public:     void updateStatus( int oState, int nState ){         if( nState > oState ){             ..... // do stuff         }     }     .... // remainder of class }

In Java, an interface is defined using the interface keyword:

 public interface StatusCallback {     void updateStatus( int oState, int nState ); }

The interface is then implemented by a class:

 public class MyClass implements StatusCallback {     public void updateStatus( int oState, int nState ){         .... // do stuff     }     .... // remainder of class }

A common pattern you’ll see with languages that support both interfaces and abstract classes is the provision of a default implementation of an interface via an abstract class. For example, the following interface:

 public interface XMLReader {     public XMLObject fromString( String str );     public XMLObject fromReader( Reader in ); }

might have this default implementation:

 public abstract class XMLReaderImpl {     public XMLObject fromString( String str ){         fromString( new StringReader( str ) );     }     public abstract XMLObject fromReader( Reader in ); }

A programmer who wanted to implement XMLReader would then have the option of creating a class that subclasses XMLReaderImpl (likely as a nested class) and only implement one method instead of two.

Virtual Methods

Important 

Describe what virtual methods are and why they are useful.

A virtual method is a method whose implementation is determined at run time based on the actual type (class) of the invoking object. Nonstatic Java methods are always virtual, so Java programmers may have trouble answering this one; but in C# and C++, methods are only virtual when declared with the virtual keyword - nonvirtual methods are the default.

Virtual methods are used for polymorphism. Consider the following three C++ classes:

 class A {   public:     void print() { cout << "A"; } } class B : A {   public:     void print() { cout << "B"; } } class C : B {   public:     void print() { cout << "C"; } }

Because print is declared as nonvirtual, the method that is invoked depends on the type used at compile time:

 A *a = new A(); B *b = new B(); C *c = new C(); a->print(); // "A" b->print(); // "B" c->print(); // "C" ((B *)c)->print(); // "B" ((A *)c)->print(); // "A" ((A *)b)->print(); // "A"

Now redeclare print as virtual:

 class A {   public:     virtual void print() { cout << "A"; } } class B : A {   public:     virtual void print() { cout << "B"; } } class C : B {   public:     virtual void print() { cout << "C"; } }

Now the run-time type of the object determines the method invoked:

 A *a = new A(); B *b = new B(); C *c = new C(); a->print(); // "A" b->print(); // "B" c->print(); // "C" ((B *)c)->print(); // "C" ((A *)c)->print(); // "C" ((A *)b)->print(); // "B"

A C++ version of the Shape class defined at the beginning of the chapter would need to declare the draw method as virtual in order for the paintShapes method - which would only have references to Shape instances - to work.

Once you explain what virtual methods are and why they’re useful, talk about their advantages and disadvantages. The primary advantage was just described: the run-time method selection. Virtual methods are also used to declare abstract methods. The disadvantages are that it takes longer to invoke a virtual method (at a minimum, one lookup needs to be done in a table to find the right method - you can’t jump directly to the method as you can with nonvirtuals) and that extra memory is required to store the information needed for the lookup.

Multiple Inheritance

Important 

Why do C# and Java disallow the multiple inheritance of classes?

In C++ it’s legal for a class to inherit (directly or indirectly) from more than one class, which is referred to as multiple inheritance. C# and Java, however, limit classes to single inheritance - each class inherits from a single parent class.

Multiple inheritance is a useful way to create classes that combine aspects of two disparate class hierarchies, something that often happens when using different class frameworks within a single application. If two frameworks define their own base classes for exceptions, for example, you can use multiple inheritance to create exception classes that can be used with either framework.

The problem with multiple inheritance is that it can lead to ambiguity. The classic example is when a class inherits from two other classes, each of which inherits from the same class:

 class A {   protected:     bool flag; }; class B : public A {}; class C : public A {}; class D : public B, public C {   public:     void setFlag( bool nflag ){         flag = nflag; // ambiguous     } };

In this example, the flag data member is defined by class A. But class D descends from class B and class C, which both derive from A, so in essence two copies of flag are available because there are two instances of A in D’s class hierarchy. Which one do you want to set? The compiler will complain that the reference to flag in D is ambiguous. One fix is to explicitly disambiguate the reference:

 B::flag = nflag;

Another fix is to declare B and C as virtual base classes, which means that only one copy of A will exist in the hierarchy, eliminating any ambiguity.

There are other complexities with multiple inheritance, such as the order in which the base classes are initialized when a derived object is constructed, or the way members can be inadvertently hidden from derived classes. Because of these complexities, some languages restrict themselves to the much simpler single inheritance model. On the other hand, single inheritance is also very restrictive, because only classes with a common ancestor can share behaviors. Interfaces mitigate this restriction somewhat by allowing classes in different hierarchies to expose common interfaces even if they’re not implemented by sharing code.




Programming Interviews Exposed. Secrets to Landing Your Next Job
Programming Interviews Exposed: Secrets to Landing Your Next Job, 2nd Edition (Programmer to Programmer)
ISBN: 047012167X
EAN: 2147483647
Year: 2007
Pages: 94

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net