Abstract type: Difference between revisions

From Rosetta Code
Content added Content deleted
No edit summary
m (J: add some words)
Line 435: Line 435:


=={{header|J}}==
=={{header|J}}==
J does not support abstract types, as defined here. In J, types are typically treated as a necessary evil, which should be disguised, hidden, neglected or ignored wherever practical. (2=1+1 regardless of the type of 1 and the type of 2.)
J does not support abstract types, as defined here. In J, types are typically treated as a necessary evil, which should be minimized, disguised, hidden, neglected or ignored wherever practical. (2=1+1 regardless of the type of 1 and the type of 2.) And allowing user defined types conflicts with this approach.


Types are sometimes thought of as being related to function domains. But, in the general case, domains of independently defined functions are independent of each other, and the intersections of these domains may or may not be empty.
Note also: Types are sometimes thought of as being related to function domains. But, in the general case, domains of independently defined functions are independent of each other, and the intersections of these domains may or may not be empty.


=={{header|Java}}==
=={{header|Java}}==

Revision as of 15:53, 14 July 2010

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 or without definition.

For example in object-oriented programming using some languages, abstract types can be partial implementations of other types, which are to be derived therefrom. An 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), classes can, nonetheless, inherit from multiple interfaces. 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, OO languages normally prevent instantiation from them (instantiation must derived from one of their descendant classes).

The term abstract datatype also may denote a type, with an implementation provided by the programmer rather than directly by the language (a built-in or an inferred type). Here the word abstract means that the implementation is abstracted away, irrelevant for the user of the type. Such implementation can and should be hidden if the language supports separation of implementation and specification. This hides complexity while allowing the implementation to change without repercussions on the usage. The corresponding software design practice is said to follow the information hiding principle.

It is important not to confuse this abstractness (of implementation) with one of the abstract type. The latter is abstract in the sense that the set of its values is empty. In the sense of implementation abstracted away, all user-defined types are abstract.

In some languages, like for example in Objective Caml which is strongly statically typed, it is also possible to have abstract types that are not OO related and are not an abstractness too. These are pure abstract types without any definition even in the implementation and can be used for example for the type algebra, or for some consistance of the type inference. For example in this area, an abstract type can be used as a phantom type to augment another type as its parameter.

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.

ActionScript

While ActionScript does not support explicit abstract classes, it does have interfaces. Interfaces in ActionScript may not implement any methods and all methods are public and implicitly abstract. Interfaces can extend other interfaces, and interfaces may be multiply inherited. <lang actionscript>package {

   public interface IInterface
   {
       function method1():void;
       function method2(arg1:Array, arg2:Boolean):uint;
   }

}</lang>

Ada

Interface

Interfaces in Ada may have no components or implemented operation except for ones implemented as null operations. Interfaces can be multiply inherited. <lang 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;</lang> Interfaces can be declared synchronized or task when intended implementations are to be provided by protected objects or tasks. For example: <lang ada>type Scheduler is task interface; procedure Plan (Manager : in out Scheduler; Activity : in out Job) is abstract;</lang>

Abstract type

Abstract types may provide components and implementation of their operations. Abstract types are singly inherited. <lang 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</lang> 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.

Aikido

An abstract class contains functions that have no body defined. You cannot instantiate a class that contains abstract functions.

<lang aikido>class Abs {

       public function method1...
       public function method2...

}</lang> Interfaces in Aikido define a set of functions, operators, classes, interfaces, monitors or threads (but no variables) that must be implemented by a class implementing the interface. <lang aikido>interface Inter {

   function isFatal : integer
   function operate (para : integer = 0) 
   operator -> (stream, isout)

}</lang>

Argile

Works with: Argile version 1.0.0

<lang Argile>use std

(: abstract class :)

class Abs

  text		name
  AbsIface	iface

class AbsIface

  function(Abs)(int)->int	method

let Abs_Iface = Cdata AbsIface@ {.method = nil}

.: new Abs :. -> Abs {let a = new(Abs); a.iface = Abs_Iface; a}

=: <Abs self>.method <int i> := -> int

  (self.iface.method is nil) ? 0 , (call self.iface.method with self i)

(: implementation :)

class Sub <- Abs { int value }

let Sub_Iface = Cdata AbsIface@ {.method = (code of (nil the Sub).method 0)}

.: new Sub (<int value = -1>) :. -> Sub

  let s = new (Sub)
  s.iface = Sub_Iface
  s.value = value
  s

.: .method <int i> :. -> int {this.value + i}

(: example use :)

.:foobar<Abs a>:. {print a.method 12 ; del a} foobar (new Sub 34) (: prints 46 :) foobar (new Sub) (: prints 11 :) foobar (new Abs) (: prints 0 :)</lang>

AutoHotkey

Works with: AutoHotkey_L

<lang AutoHotkey>color(r, g, b){

  static color
  If !color 
     color := Object("base", Object("R", r, "G", g, "B", b 
                                   ,"GetRGB", "Color_GetRGB"))
  return  Object("base", Color) 

} Color_GetRGB(clr) {

   return "not implemented"

}

waterColor(r, g, b){

  static waterColor
  If !waterColor 
     waterColor := Object("base", color(r, g, b),"GetRGB", "WaterColor_GetRGB")
  return  Object("base", WaterColor) 

}

WaterColor_GetRGB(clr){ return clr.R << 16 | clr.G << 8 | clr.B }

test: blue := color(0, 0, 255) msgbox % blue.GetRGB() ; displays "not implemented" blue := waterColor(0, 0, 255) msgbox % blue.GetRGB() ; displays 255 return </lang>

C

Doing abstract types in C is not particularly trivial as C doesn't really support classes. The following series will show an abstract type, followed by a realizable class that provides the abstract interface, and finally followed by an example of usage.

The header file for the abstract class, interfaceAbs.h <lang c>#ifndef INTERFACE_ABS

  1. define INTERFACE_ABS

typedef struct sAbstractCls *AbsCls;

typedef struct sAbstractMethods {

   int         (*method1)(AbsCls c, int a);
   const char *(*method2)(AbsCls c, int b);
   void        (*method3)(AbsCls c, double d);

} *AbstractMethods, sAbsMethods;

struct sAbstractCls {

   AbstractMethods  klass;
   void     *instData;

};

  1. define ABSTRACT_METHODS( cName, m1, m2, m3 ) \
   static sAbsMethods cName ## _Iface = { &m1, &m2, &m3 }; \
   AbsCls cName ## _Instance( void *clInst) { \
       AbsCls ac = malloc(sizeof(struct sAbstractCls)); \
       if (ac) { \
           ac->klass = &cName ## _Iface; \
           ac->instData = clInst; \
       }\
       return ac; }
  1. define Abs_Method1( c, a) (c)->klass->method1(c, a)
  2. define Abs_Method2( c, b) (c)->klass->method2(c, b)
  3. define Abs_Method3( c, d) (c)->klass->method3(c, d)
  4. define Abs_Free(c) \
 do { if(c && c->instData) free(c->instData); if (c) free(c); } while(0);

  1. endif</lang>

That will define the abstract class. The next section declares a public interface for a class providing the interface of the abstract class. This class is Silly and the code is in file silly.h. Note the actual structure of the class is not provided here. We don't want it visible. <lang c>#ifndef SILLY_H

  1. define SILLY_H
  2. include intefaceAbs.h

typedef struct sillyStruct *Silly; extern Silly NewSilly( double, const char *); extern AbsCls Silly_Instance(void *);

  1. endif</lang>

Ok. Now it is necessary to provide the implementation of the realizable class. This code should be in silly.c. <lang c>#include "silly.h"

  1. include <string.h>
  2. include <stdlib.h>
  3. include <stdio.h>

struct sillyStruct {

   double  v1;
   char   str[32];

};

Silly NewSilly(double vInit, const char *strInit) {

   Silly sily = malloc(sizeof( struct sillyStruct ));
   sily->v1 = vInit;
   sily->str[0] = '\0';
   strncat(sily->str, strInit, 31);
   return sily;

}

static int MyMethod1( AbsCls c, int a) {

   Silly s = (Silly)(c->instData);
   return a+strlen(s->str);

}

static const char *MyMethod2(AbsCls c, int b) {

   Silly s = (Silly)(c->instData);
   sprintf(s->str, "%d", b);
   return s->str;

}

static void MyMethod3(AbsCls c, double d) {

   Silly s = (Silly)(c->instData);
   printf("InMyMethod3, %f\n",s->v1 * d);

}

ABSTRACT_METHODS( Silly, MyMethod1, MyMethod2, MyMethod3)</lang> That last macro, ABSTRACT_METHODS may need a little explanation. First note that macros do a string substitution of the parameter values into the arguments of the defined macro, with a little hitch. In the macro definition the ' ## ' expression is special. Here cName ## _Iface gets converted to Silly_Iface, as 'Silly' replaces cName. So the macro call declares an instance of the class record, and defines a constructor named Silly_Instance, which takes a Silly structure as an arguments and uses the class record it previously set up as well.

The methods MyMethod1, MyMethod2, and MyMethod3 are called through the abstract class interface and do not need to be visible outside this file. Hence, they are declared static.

Now all's left is some example code that uses all this stuff. <lang c>#include <stdio.h>

  1. include "silly.h"

int main() {

   AbsCls abster = Silly_Instance(NewSilly( 10.1, "Green Tomato"));
   printf("AbsMethod1: %d\n", Abs_Method1(abster, 5));
   printf("AbsMethod2: %s\n", Abs_Method2(abster, 4));
   Abs_Method3(abster, 21.55);
   Abs_Free(abster);
   return 0;

} </lang>

C#

<lang csharp>abstract class Class1 {

  public abstract void method1();
  public int method2()
  {
     return 0;
  }

}</lang>

C++

You can declare a virtual function to not have an implementation (called "pure virtual function") by the following "= 0" syntax after the method declaration. A class containing at least one pure virtual function (or inheriting one and not overriding it) cannot be instantiated. <lang cpp>class Abs { public: virtual int method1(double value) = 0; virtual int add(int a, int b){ return a+b; } };</lang> Because C++ allows multiple inheritance of classes, no distinction is made between interfaces and abstract classes.

Clojure

Using defprotocol, we can define what is essentially an interface.

<lang lisp>(defprotocol Foo (foo [this]))</lang>

Common Lisp

In Common Lisp, classes do not implement methods, but methods specialized for particular kinds of arguments may be defined for generic functions. Since we can programmatically determine whether methods are defined for a list of arguments, we can simulate a kind of abstract type. We define an abstract type kons to which an object belongs if methods for kar and kdr are defined for it. We define a type predicate konsp and a type kons in terms of the type predicate.

<lang lisp>(defgeneric kar (kons)

 (:documentation "Return the kar of a kons."))

(defgeneric kdr (kons)

 (:documentation "Return the kdr of a kons."))

(defun konsp (object &aux (args (list object)))

 "True if there are applicable methods for kar and kdr on object."
 (not (or (endp (compute-applicable-methods #'kar args))
          (endp (compute-applicable-methods #'kdr args)))))

(deftype kons ()

 '(satisfies konsp))</lang>

We can make the built-in types cons and integer konses. We start with cons, using the obvious definitions.

<lang lisp>(defmethod kar ((cons cons))

 (car cons))

(defmethod kdr ((cons cons))

 (cdr cons))

(konsp (cons 1 2))  ; => t (typep (cons 1 2) 'kons) ; => t (kar (cons 1 2))  ; => 1 (kdr (cons 1 2))  ; => 2</lang>

For integers, we'll define the kar of n to be 1 and the kdr of n to be n - 1. This means that for an integer n, n = (+ (kar n) (kdr n)).

<lang lisp>(defmethod kar ((n integer))

 1)

(defmethod kdr ((n integer))

 (if (zerop n) nil
   (1- n)))

(konsp 45)  ; => t (typep 45 'kons)  ; => t (kar 45)  ; => 1 (kdr 45)  ; => 44</lang>

D

<lang d>class Foo {

 abstract void foo() { writefln("Test"); } // abstract methods can have an implementation for use in super calls

}

interface Bar {

 // interface methods are implicitly abstract and cannot provide default implementations
 void bar();

}

class Baz : Foo, Bar { // super class must come first

 void foo() { writefln("Meep"); super.foo(); }
 void bar() { }

}</lang>

E

In E, the implementation of an object is never used to determine type membership (except when dealing with the host platform's objects if it uses such distinctions, such as the JVM), so all types are abstract.

A simple abstract type without enforcement can be created using the interface expression:

<lang e>interface Foo {

   to bar(a :int, b :int)

}</lang>

With enforcement, a separate stamp is created which must be applied to the instances. This is analogous to a Java interface.

<lang e>interface Foo guards FooStamp {

   to bar(a :int, b :int)

}

def x implements FooStamp {

   to bar(a :int, b :int) {
       return a - b
   }

}</lang>

Genyris

In Genyris by default there are no constructors. In effect all classes are Abstract until they are used to tag (describe) an object. This in keeping with the language's roots in Description Logic. To prevent the class ever being associated with an instance it suffices to force the validator to fail. <lang genyris>class AbstractStack()

  def .valid?(object) nil

tag AbstractStack some-object # always fails</lang>

However this is not much use if we want to use an abstract class to define an interface. Here is a quasi-abstract class which can be used to tag objects if they conform to the class's membership expectations. In this case it wants two methods, .enstack and .destack: <lang genyris>class StackInterface()

  def .valid?(object)
     object
        and
           bound? .enstack
           is-instance? .enstack Closure
           bound? .destack
           is-instance? .destack Closure</lang>

So if ever we find an object which conforms to the validator it can be tagged. Here's a 'traditional' class definition using the Object class which does provide a constructor: <lang genyris>class XYZstack(Object)

   def .init()
       var .items ()
   def .enstack(object)
       .items = (cons object .items)
   def .destack()
       var tmp  (car .items)
       .items = (cdr .items)
       tmp</lang>

Now we can tag an object that conforms to the Interface: <lang genyris>tag StackInterface (XYZstack(.new))</lang>

Haskell

In Haskell an abstract type is a type class. A type class specifies an interface. One can then define "instances" to provide implementations of the type class for various types.

For example, the built-in type class Eq (the types that can be compared for equality) can be declared as follows: <lang haskell>class Eq a where

  (==) :: a -> a -> Bool
  (/=) :: a -> a -> Bool</lang>

Default implementations of the functions can be provided: <lang haskell>class Eq a where

  (==) :: a -> a -> Bool
  (/=) :: a -> a -> Bool
  x /= y     =  not (x == y)
  x == y     =  not (x /= y)</lang>

Here default implementations of each of the operators is circularly defined in terms of the other, for convenience of the programmer; so the programmer only needs to implement one of them for it to work.

Consider the following function which uses the operator == of the type class Eq from above. The arguments to == above were of the unknown type "a", which is of class Eq, so the type of the expression below now must include this restriction: <lang haskell>func :: (Eq a) => a -> Bool func x = x == x</lang>

Suppose I make a new type <lang haskell>data Foo = Foo {x :: Integer, str :: String}</lang>

One could then provide an implementation ("instance") the type class Eq with this type <lang haskell>instance Eq Foo where

  (Foo x1 str1) == (Foo x2 str2) =
     (x1 == x2) && (str1 == str2)</lang>

And now I can, for example, use the function "func" on two arguments of type Foo.

Icon and Unicon

Icon

Icon is not object-oriented.

Unicon

Unicon does not distinguish between abstract and concrete classes. However, programmers may detect unimplemented methods using the same approach as with other, similar languages. <lang unicon>class abstraction()

   method compare(l,r)
       runerr(1038, "method compare in class abstraction")
   end

end</lang>

J

J does not support abstract types, as defined here. In J, types are typically treated as a necessary evil, which should be minimized, disguised, hidden, neglected or ignored wherever practical. (2=1+1 regardless of the type of 1 and the type of 2.) And allowing user defined types conflicts with this approach.

Note also: Types are sometimes thought of as being related to function domains. But, in the general case, domains of independently defined functions are independent of each other, and the intersections of these domains may or may not be empty.

Java

Methods that don't have an implementation are called abstract methods in Java. A class that contains an abstract method or inherits one but did not override it must be an abstract class; but an abstract class does not need to contain any abstract methods. An abstract class cannot be instantiated. If a method is abstract, it must be public or protected <lang 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; } }</lang> Interfaces in Java may not implement any methods and all methods are implicitly public and abstract. <lang java>public interface Inter { int method1(double value); int method2(String name); int add(int a, int b); }</lang>

Lua

Lua does not include built-in object oriented paradigms. These features can be added using simple code such as the following: <lang lua>BaseClass = {}

function class ( baseClass )

   local new_class = {}
   local class_mt = { __index = new_class }
   function new_class:new()
       local newinst = {}
       setmetatable( newinst, class_mt )
       return newinst
   end
   if not baseClass then baseClass = BaseClass end
       setmetatable( new_class, { __index = baseClass } )
   return new_class

end

function abstractClass ( self )

   local new_class = {}
   local class_mt = { __index = new_class }
   function new_class:new()
       error("Abstract classes cannot be instanciated")
   end
   if not baseClass then baseClass = BaseClass end
       setmetatable( new_class, { __index = baseClass } )
   return new_class

end

BaseClass.class = class BaseClass.abstractClass = abstractClass</lang> The 'class' function produces a new class from an existing parent class (BaseClass is default). From this class other classes or instances can be created. If a class is created through the 'abstractClass' function, however, the resulting class will throw an error if one attempts to instanciate it. Example: <lang lua>A = class() -- New class A inherits BaseClass by default AA = A:class() -- New class AA inherits from existing class A B = abstractClass() -- New abstract class B BB = B:class() -- BB is not abstract A:new() -- Okay: New class instance AA:new() -- Okay: New class instance B:new() -- Error: B is abstract BB:new() -- Okay: BB is not abstract</lang>

Objeck

<lang objeck> class ClassA {

  method : virtual : public : MethodA(), Int;

  method : public : MethodA(), Int {
     return 0;
  }

} </lang>

OCaml

Virtual

The equivalent of what is called abstract type in the other OO examples of this page is just called virtual in Objective Caml to define virtual methods and virtual classes:

<lang ocaml>class virtual foo =

 object
   method virtual bar : int
 end</lang>

Abstract Type

In OCaml what we call an abstract type is not OO related, it is only a type defined without definition, for example: <lang ocaml>type t</lang> it is used for example to hide an implementation from the interface of a module or for type algebra.

Example of abstracting a type in an interface: <lang ocaml>module Foo : sig

 type t

end = struct

 type t = int * int

end</lang>

Pure abstract types in the implementation: <lang ocaml>type u type v type 'a t type ut = u t type vt = v t</lang>

Oz

Translation of: Python

There are no abstract types as part of the language, but we can do as in Python and raise exceptions:

<lang oz>declare

 class BaseQueue
    attr
       contents:nil
     
    meth init
       raise notImplemented(self init) end
    end
    meth enqueue(Item)
       raise notImplemented(self enqueue) end
    end
    meth dequeue(?Item)
       raise notImplemented(self dequeue) end
    end
    meth printContents
       {ForAll @contents Show}
    end
 end
 Queue = {New BaseQueue init} %% throws</lang>

Perl

<lang perl>package AbstractFoo;

use strict;

sub frob { die "abstract" } sub baz { die "abstract" }

sub frob_the_baz {

   my $self = shift;
   $self->frob($self->baz());

}


1;</lang>

PHP

The following is for PHP 5.

Methods that don't have an implementation are called abstract methods in PHP. A class that contains an abstract method or inherits one but did not override it must be an abstract class; but an abstract class does not need to contain any abstract methods. An abstract class cannot be instantiated. If a method is abstract, it must be public or protected <lang php>abstract class Abs { abstract public function method1($value); abstract protected function method2($name); function add($a, $b){ return a + b; } }</lang> Interfaces in PHP may not implement any methods and all methods are public and implicitly abstract. <lang php>interface Inter { public function method1($value); public function method2($name); public function add($a, $b); }</lang>

PicoLisp

<lang PicoLisp># In PicoLisp there is no formal difference between abstract and concrete

  1. classes, just a naming convention where abstract classes start with a
  2. lower case character after the '+' (the naming convention for classes).
  3. This tells the programmer that this class has not sufficient methods
  4. defined to survive on its own.

(class +abstractClass)

(dm someMethod> ()

  (foo)
  (bar) )</lang>

Python

<lang 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
   def Print_Contents(self):
       for i in self.contents:
           print i,</lang>

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 interfaces).

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 its concrete (fully implemented) 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).

In this case we've implemented one method (Print_Contents). This would be inherited by any derived classes. It could be over-ridden, of course. If it's not over-ridden it establishes a requirement that all derived classes provide some "contents" attribute which must allow for iteration and printing as shown. Without this method the class would be "purely virtual" or "purely abstract." With its inclusion the class becomes "partially implemented."

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).

REBOL

<lang REBOL>REBOL [ Title: "Abstract Type" Author: oofoe Date: 2009-12-05 URL: http://rosettacode.org/wiki/Abstract_type ]

The "shape" class is an abstract class -- it defines the "pen"
property and "line" method, but "size" and "draw" are undefined and
unimplemented.

shape: make object! [ pen: "X" size: none

line: func [count][loop count [prin self/pen] prin crlf] draw: does [none] ]

The "box" class inherits from "shape" and provides the missing
information for drawing boxes.

box: make shape [ size: 10 draw: does [loop self/size [line self/size]] ]

"rectangle" also inherits from "shape", but handles the
implementation very differently.

rectangle: make shape [ size: 20x10 draw: does [loop self/size/y [line self/size/x]] ]

Unlike some languages discussed, REBOL has absolutely no qualms
about instantiating an "abstract" class -- that's how I created the
derived classes of "rectangle" and "box", after all.

s: make shape [] s/draw ; Nothing happens.

print "A box:" b: make box [pen: "O" size: 5] b/draw

print [crlf "A rectangle:"] r: make rectangle [size: 32x5] r/draw</lang>

Ruby

The Python and Tcl provisos apply to Ruby too. Nevertheless, a

Library: RubyGems

package called abstraction exists where:

<lang ruby>require 'abstraction'

class AbstractQueue

 abstract
 def enqueue(object)
   raise NotImplementedError
 end
 def dequeue
   raise NotImplementedError
 end

end

class ConcreteQueue < AbstractQueue

 def enqueue(object)
   puts "enqueue #{object.inspect}"
 end

end</lang> So:

irb(main):032:0> a = AbstractQueue.new
AbstractClassError: AbstractQueue is an abstract class and cannot be instantiated
        from /usr/lib/ruby/gems/1.8/gems/abstraction-0.0.3/lib/abstraction.rb:10:in `new'
        from (irb):32
        from :0
irb(main):033:0> c = ConcreteQueue.new
=> #<ConcreteQueue:0x7fdea114>
irb(main):034:0> c.enqueue('foo')
enqueue "foo"
=> nil
irb(main):040:0> c.dequeue
NotImplementedError: NotImplementedError
        from (irb):37:in `dequeue'
        from (irb):40
        from :0

Scala

Scala has abstract classes, which are classes that cannot be instantiated. They can contain implementation as well as just interface. Non-abstract classes, on the other hand, cannot contain interfaces without implementation.

Scala also has traits, which may contain implementations or not as needed, without any abstract requirement. On the other hand, traits must be mixed in a class, instead of being directly instantiated. That doesn't matter all that much, as they can be mixed with AnyRef, which is the base parent class of all user-defined classes.

Any element of a trait or class can be made abstract, including types, with a very different meaning that described in this page. Here are some examples:

<lang scala>abstract class X {

 type A
 var B: A
 val C: A
 def D(a: A): A

}

trait Y {

 val x: X

}</lang>

When integrating with Java, traits without implementation appear as interfaces.

Tcl

Works with: Tcl version 8.6

While in general Tcl does not use abstract classes at all (and has no need at all for interfaces due to supporting multiple inheritance and mixins), an equivalent effect can be had by concealing the construction methods on the class instance; instances are only created by subclassing the class first (or by mixing it in). In this example, the methods are also error-returning stubs... <lang Tcl>oo::class create AbstractQueue {

   method enqueue item {
       error "not implemented"
   }
   method dequeue {} {
       error "not implemented"
   }
   self unexport create new

}</lang>

Visual Basic

Abstract Classes

Visual Basic doesn't support abstract classes or implementation inheritance.

Interfaces

In Visual Basic, every class is also an interface that other classes can implement. It has this feature because it is based on COM.

Visual Basic .NET

Abstract Classes

  • Overridable means subclasses may change the method's implementation. By default, methods in VB cannot be overridden.
  • MustOverride means the subclasses must provide an implementation
  • By convention all abstract classes have one or more Protected constructors.

<lang vbnet>MustInherit Class Base

  Protected Sub New()
  End Sub
  Public Sub StandardMethod()
      'code
  End Sub
  Public Overridable Sub Method_Can_Be_Replaced()
      'code
  End Sub
  Public MustOverride Sub Method_Must_Be_Replaced()

End Class</lang>

Interfaces

Interfaces may contain Functions, Subroutines, Properties, and Events.

<lang vbnet>Interface IBase

  Sub Method_Must_Be_Implemented()

End Interface</lang>