Abstract type: Difference between revisions

From Rosetta Code
Content added Content deleted
m (Typos)
m (→‎Abstract type: Typo fixed)
Line 24: Line 24:
Abstract types may provide components and implementation of their operations. Abstract types are singly inherited.
Abstract types may provide components and implementation of their operations. Abstract types are singly inherited.
<ada>
<ada>
with Ada.Finalization.Limited_Controlled;
with Ada.Finalization;
...
...
type Node is abstract new Ada.Finalization.Limited_Controlled and Queue with record
type Node is abstract new Ada.Finalization.Limited_Controlled and Queue with record

Revision as of 18:28, 20 November 2008

Task
Abstract type
You are encouraged to solve this task according to the task description, using any language you may know.

Abstract type is a type without instances. In object-oriented programming abstract types are used for partial implementation of other types, which are later derived from it. Abstract type may provide implementation of some operations and/or components. Abstract types without any implementation are called interfaces. In the languages that do not support multiple inheritance (Ada, Java), interfaces are usually allowed to be multiply inherited from. The languages with multiple inheritance (like C++) usually make no distinction between partially implementable abstract types and interfaces.

Because the abstract type's implementation is incomplete, if any, it makes no sense to have any instances (objects) of it. Therefore an OO language would prevent creation of such objects.

Task: show how an abstract type can be declared in the language. If the language makes a distinction between interfaces and partially implemented types illustrate both.

Ada

Interface

Interfaces in Ada may have no components or implemented operation except for ones implemented as null operations. Interfaces can be multiply inherited. <ada> type Queue is limited interface; procedure Enqueue (Lounge : in out Queue; Item : in out Element) is abstract; procedure Dequeue (Lounge : in out Queue; Item : in out Element) is abstract; </ada> Interfaces can be declared synchronized or task when intended implementations are to be provided by protected objects or tasks. For example: <ada> type Scheduler is task interface; procedure Plan (Manager : in out Scheduler; Activity : in out Job) is abstract; </ada>

Abstract type

Abstract types may provide components and implementation of their operations. Abstract types are singly inherited. <ada> with Ada.Finalization; ... type Node is abstract new Ada.Finalization.Limited_Controlled and Queue with record

  Previous : not null access Node'Class := Node'Unchecked_Access;
  Next     : not null access Node'Class := Node'Unchecked_Access;

end record; overriding procedure Finalize (X : in out Node); -- Removes the node from its list if any overriding procedure Dequeue (Lounge : in out Node; Item : in out Element); overriding procedure Enqueue (Lounge : in out Node; Item : in out Element); procedure Process (X : in out Node) is abstract; -- To be implemented </ada> Here Node is an abstract type that is inherited from Limited_Controlled and implements a node of a doubly linked list. It also implements the interface of a queue described above, because any node can be considered a head of the queue of linked elements. For the operation Finalize an implementation is provided to ensure that the element of a list is removed from there upon its finalization. The operation itself is inherited from the parent type Limited_Controlled and then overridden. The operations Dequeue and Enqueue of the Queue interface are also implemented.

Java

Abstract classes in Java can define methods and aren't required to have abstract methods. If a method is abstract, it must be public or protected <java>public abstract class Abs { abstract public int method1(double value); abstract protected int method2(String name); int add(int a, int b){ return a+b; } }</java> Interfaces in Java may not define any methods and all methods must be public and can be abstract. <java>public interface Inter { public int method1(double value); public int method2(String name); abstract public int add(int a, int b); }</java>

Python

<python>

  class BaseQueue(object):
      """Abstract/Virtual Class 
      """
      def __init__(self):
          self.contents = list()
          raise NotImplementedError
      def Enqueue(self, item):
          raise NotImplementedError
      def Dequeue(self):
          raise NotImplementedError

</python>

Python allows multiple inheritance and it's more common to implement "mix-in" classes rather than abstract interfaces. (Mix-in classes can implement functionality as well define interaces).

In this example we're simply following the Python convention of raising the built-in "NotImplementedError" for each function which must be implemented by our subclasses. This is a "purely virtual" class because all of its methods raise the exception. (It is sufficient for __init__ to do so for any partial virtual abstractions since that still ensures that the exception will be raised if anyone attempts to instantiate the base/abstract class directly rather than one of it's concrete descendents).

The method signatures and the instantiation of a "contents" list shown here can be viewed as documentary hints to anyone inheriting from this class. They won't actually do anything in the derived classes (since these methods must be over-ridden therein).

Note: This "BaseQueue" example should not be confused with Python's standard library Queue class. That is used as the principle "producer/consumer" communications mechanism among threads (and newer multiprocessing processes).