Jump to content

Abstract type

From Rosetta Code
(Redirected from Interface)
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 there-from. 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 consistence 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.


11l

You can declare a virtual function to not have an implementation by using F.virtual.abstract keyword. A type containing at least one abstract virtual function cannot be instantiated.

T AbstractQueue
   F.virtual.abstract enqueue(Int item) -> Void

T PrintQueue(AbstractQueue)
   F.virtual.assign enqueue(Int item) -> Void
      print(item)

AArch64 Assembly

ABAP

Abstract Class

class abs definition abstract.
  public section.
    methods method1 abstract importing iv_value type f exporting ev_ret type i.
  protected section.
    methods method2 abstract importing iv_name type string exporting ev_ret type i.
    methods add importing iv_a type i iv_b type i exporting ev_ret type i.
endclass.

class abs implementation.
  method add.
    ev_ret = iv_a + iv_b.
  endmethod.
endclass.

Interfaces

Interfaces in ABAP are classes with the following restrictions: 1. All methods must be abstract instance methods (Static methods aren't allowed). 2. Variables must be static final. The values may be computed at run time. 3. No static initialiser blockers. No static initialiser helper methods.

interface inter.
  methods: method1 importing iv_value type f exporting ev_ret type i,
           method2 importing iv_name type string exporting ev_ret type i,
           add importing iv_a type i iv_b type i exporting ev_ret type i.
endinterface.

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.

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

Abstract types can also be simulated using the built-in flash.utils.getQualifiedClassName() function in the constructor to check that the runtime type is an inhertied class, and throwing exceptions from "abstract" methods which can be overridden by inheritors to disable them. If any inheriting class does not implement an abstract method, the error will not be thrown until the non-implemented method is called.

package {
    import flash.utils.getQualifiedClassName;

    public class AbstractClass {
        
        private static const FULLY_QUALIFIED_NAME:String = "AbstractClass";
        
        // For classes in a package, the fully qualified name should be in the form "package.name::class_name"
        // Note that a double colon and not a dot is used before the class name. This is the format returned
        // by the getQualifiedClassName() function.
        
        public function AbstractClass() {
            if ( getQualifiedClassName(this) == FULLY_QUALIFIED_NAME )
                throw new Error("Class " + FULLY_QUALIFIED_NAME + " is abstract.");
        }
        
        public function abstractMethod(a:int, b:int):void {
            throw new Error("abstractMethod is not implemented.");
        }
        
    }
}

Inheriting this class:

package {

    public class Example extends AbstractClass {

        override public function abstractMethod(a:int, b:int):void {
            trace(a + b);
        }
        
    }
}

Ada

Interface

Interfaces in Ada may have no components or implemented operation except for ones implemented as null operations. Interfaces can be multiply inherited.

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;

Interfaces can be declared synchronized or task when intended implementations are to be provided by protected objects or tasks. For example:

type Scheduler is task interface;
procedure Plan (Manager : in out Scheduler; Activity : in out Job) is abstract;

Abstract type

Abstract types may provide components and implementation of their operations. Abstract types are singly inherited.

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

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.

Agda

Using records for storing the interface methods and instance arguments (which are similar to Haskell type classes) for overloading:

module AbstractInterfaceExample where

open import Function
open import Data.Bool
open import Data.String

-- * One-parameter interface for the type `a' with only one method.

record VoiceInterface (a : Set) : Set where
  constructor voice-interface
  field say-method-of : a  String

open VoiceInterface

-- * An overloaded method.

say : {a : Set}   _ : VoiceInterface a   a  String
say  instance  = say-method-of instance

-- * Some data types.

data Cat : Set where
  cat : Bool  Cat

crazy! = true
plain-cat = false

-- | This cat is crazy?
crazy? : Cat  Bool
crazy? (cat x) = x

-- | A 'plain' dog.
data Dog : Set where
  dog : Dog

-- * Implementation of the interface (and method).

instance-for-cat : VoiceInterface Cat
instance-for-cat = voice-interface case where
  case : Cat  String
  case x with crazy? x
  ... | true = "meeeoooowwwww!!!"
  ... | false = "meow!"

instance-for-dog : VoiceInterface Dog
instance-for-dog = voice-interface $ const "woof!"

-- * and then:
-- 
-- say dog => "woof!"
-- say (cat crazy!) => "meeeoooowwwww!!!"
-- say (cat plain-cat) => "meow!"
--

There is dog and cat is objects of different types for which the interface method is implemented.

Aikido

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

class Abs {
        public function method1...
        public function method2...

}

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.

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

AmigaE

In AmigaE, abstract methods are supported but interfaces are not.

OBJECT fruit
ENDOBJECT

PROC color OF fruit IS EMPTY

OBJECT apple OF fruit
ENDOBJECT

PROC color OF apple IS WriteF('red ')

OBJECT orange OF fruit
ENDOBJECT

PROC color OF orange IS WriteF('orange ')

PROC main()
  DEF a:PTR TO apple,o:PTR TO orange,x:PTR TO fruit
  FORALL({x},[NEW a, NEW o],`x.color())
ENDPROC

prints to the console:

red orange

Apex

// Interface
public interface PurchaseOrder {
    // All other functionality excluded
    Double discount();
}

// One implementation of the interface for customers
public class CustomerPurchaseOrder implements PurchaseOrder {
    public Double discount() {
        return .05;  // Flat 5% discount
    }
}


// Abstract Class
public abstract class AbstractExampleClass {
	protected abstract Integer abstractMethod();
}

// Complete the abstract class by implementing its abstract method
public class Class1 extends AbstractExampleClass {
	public override Integer abstractMethod() { return 5; }
}

Argile

Works with: Argile version 1.0.0
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

.: <Sub this>.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 :)


AutoHotkey

Works with: AutoHotkey_L
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

BASIC

BBC BASIC

BBC BASIC is a procedural language with no built-in OO features. The CLASSLIB library implements simple Object Classes with multiple inheritance; an abstract class may be created without any instantiation, the sole purpose of which is for other classes to inherit from it. At least one member or method must be declared, but no error will be generated if there is no implementation:

      INSTALL @lib$+"CLASSLIB"
      
      REM Declare a class with no implementation:
      DIM abstract{method}
      PROC_class(abstract{})
      
      REM Inherit from the abstract class:
      DIM derived{member%}
      PROC_inherit(derived{}, abstract{})
      PROC_class(derived{})
      
      REM Provide an implementation for the derived class:
      DEF derived.method : PRINT "Hello world!" : ENDPROC
      
      REM Instantiate the derived class:
      PROC_new(instance{}, derived{})
      
      REM Test by calling the method:
      PROC(instance.method)

QB64

QB64, along with QBasic and QuickBasic (without extension), is not Object-Oriented; however, the following addresses issues raised in the description of the problem as well as the problem itself:

'Keep in mind that this code DOES NOT follow appropriate coding structure, but is used for easiest explanation. That
'said, the following is both legal and executable.

a = 15 'Addressing the point raised regarding hiding complexity from the programmer, QB64 follows the QBasic/QuickBasic paradigm
       'of not requiring the programmer to declare the type of a variable at all. In fact, variables can be used without any prior
       'declaration or DIMensioning. So, in this way an undeclared variable is somewhat similar to a VOID in C/C++; however,
       'unlike a VOID, the undeclared variable in QB64 DOES have a type, but the programmer need not be concerned with what it is.

Type c           'The closest to having Classes QB64 comes, being not OO, is user-defined types, which are containers of multiple
                 'values of same or different types. This is a declaration of a user-defined type named "c" which has the
                 'following elements:
    d As Integer 'This is the declaration of variable "d", which is an element (notice the lack of the use of the word "member") of
                 'the user-defined type "c".
    e As String  'As mentioned above the user-defined type, in this case "c", can have constituent elements of differing types.
End Type         'Notice that since this is a user-defined type and not an object, there are no methods defined within it. For this
                 'example defining a member of "c" as both a SUBroutine and a FUNCTION was attempted, neither of which was
                 'successful. It should also be noted that it is illegal to define a user-defined type without any elements. Put 
                 'another way, all user-defined types require at least one element. 


Type f           'As QB64 is not OO, it does not have true inheritence; however, the nesting of user-defined types is allowed, which
                 'allows for an attempt at inheritance, as close as QB64 can come. As well as pseudo-abstracting the type "c", which
                 'need not ever be directly accessed, although since instantiation occurs at declaration, memory allocation is most
                 'likely made for it.
    g As c       'This is the declaration of a user-defined type as an element of another user-defined type. If "c" were used
                 'nowhere else in the program, but only here as a variable type, the pseudo-abstraction is achieved.
    h As Integer
End Type

c.d = 25         'This is the way in which elements of user-defined types are accessed. Here the type "c" has been directly accessed
                 'and thus eliminates any such pseudo-abstraction as mentioned above.

Dim i As f               'This is the declaration of a variable of the user-defined type "f", which allows for the following.
i.g.e = "thirty five"    'This is the way in which the element of a user-define type containing another user-defined type as an
                         'element is access. In this way, user-defined type "f" has been pseudo-abstracted since its elements are
                         'never directly referenced in the rest of this program, even though memory has been allocated for it and its
                         'constituent elements.
Dim j As f               'This is a second instance of the user-defined type "f", showing that "f" has been pseudo-abstracted, even
                         'though "f" does exist in its own right in memory.
j.g.e = "forty five"

Print a
Print b
Print c.d
Print c.e
Print i.g.e        'This is another use of the previously declared variable "i" and its element "g"'s element "e".
Print g.e          'This is NOT a use of the above variable "i" or any of its elements. Since QB64 does not require strict typing
                   'nor contain a typeOf() function, it is unclear of what type "g.e" is, although it is suspected that it is either
                   'an Integer or a String, being a use of type "c"'s element "d" or "e".
Print j.g.e
System
Output:
15
0
25
0
thirty five
0
forty five

QBasic

Works with: QBasic version 1.1
Works with: QuickBasic version 4.5
Translation of: QB64
a = 15
 
TYPE c
    d AS INTEGER
    e AS STRING * 12
END TYPE
c.d = 25

TYPE f
    g AS c
    h AS INTEGER
END TYPE
 
DIM i AS f
i.g.e = "thirty five"

DIM j AS f
j.g.e = "forty five"

PRINT a
PRINT b
PRINT c.d
PRINT c.e
PRINT i.g.e
PRINT g.e
PRINT j.g.e


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

#ifndef INTERFACE_ABS
#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;
};

#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; }

#define Abs_Method1( c, a) (c)->klass->method1(c, a)
#define Abs_Method2( c, b) (c)->klass->method2(c, b)
#define Abs_Method3( c, d) (c)->klass->method3(c, d)
#define Abs_Free(c) \
  do { if (c) { free((c)->instData); free(c); } } while(0);
 
#endif

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.

#ifndef SILLY_H
#define SILLY_H
#include "intefaceAbs.h"
#include <stdlib.h>

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

#endif

Ok. Now it is necessary to provide the implementation of the realizable class. This code should be in silly.c.

#include "silly.h"
#include <string.h>
#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)

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.

#include <stdio.h>
#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;
}

C#

abstract class Class1
{
   public abstract void method1();

   public int method2()
   {
      return 0;
   }
}

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.

class Abs {
public:
	virtual int method1(double value) = 0;
	virtual int add(int a, int b){
		return a+b;
	}
};

Because C++ allows multiple inheritance of classes, no distinction is made between interfaces and abstract classes.

Caché ObjectScript

In Caché, abstract and data type classes cannot be instantiated directly - there must be a 'concrete subclass' that extends them as well as the '%RegisteredObject' class in order to instantiate an object, see example below.

Class Abstract.Class.Shape [ Abstract ]
{
Parameter SHAPE = 1;
Property Name As %String;
Method Description() {}
}

Class Abstract.Class.Square Extends (%RegisteredObject, Shape)
{
Method Description()
{
	Write "SHAPE=", ..#SHAPE, !
	Write ..%ClassName()_$Case(..%Extends(..%PackageName()_".Shape"), 1: " is a ", : " is not a ")_"shape"
}
}

Data type classes differ because they cannot contain properties, see example below.

Class Abstract.DataType.Shape [ ClassType = datatype ]
{
Parameter SHAPE = 1;
Method Description() {}
}

Class Abstract.DataType.Square Extends (%RegisteredObject, Shape)
{
Method Description()
{
	Write "SHAPE=", ..#SHAPE, !
	Write ..%ClassName()_$Case(..%Extends(..%PackageName()_".Shape"), 1: " is a ", : " is not a ")_"shape"
}
}

Both class types can contain implementation code. Caché allows multiple inheritance of classes, so no distinction is made between abstract classes and interfaces.

Examples:
USER>Do ##class(Abstract.Class.Square).%New().Description()
SHAPE=1
Square is a shape

USER>Do ##class(Abstract.DataType.Square).%New().Description()
SHAPE=1
Square is a shape

Clojure

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

(defprotocol Foo (foo [this]))

COBOL

Interface

Translation of: F#
       IDENTIFICATION DIVISION.
       INTERFACE-ID. Shape.
       
       PROCEDURE DIVISION.
       
       IDENTIFICATION DIVISION.
       METHOD-ID. perimeter.
       DATA DIVISION.
       LINKAGE SECTION.
       01  ret USAGE FLOAT-LONG.
       PROCEDURE DIVISION RETURNING ret.
       END METHOD perimeter.
       
       IDENTIFICATION DIVISION.
       METHOD-ID. shape-area.
       DATA DIVISION.
       LINKAGE SECTION.
       01  ret USAGE FLOAT-LONG.
       PROCEDURE DIVISION RETURNING ret.
       END METHOD shape-area.
       
       END INTERFACE Shape.
       

       IDENTIFICATION DIVISION.
       CLASS-ID. Rectangle. 
       
       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
       REPOSITORY.
           INTERFACE Shape.
       
       IDENTIFICATION DIVISION.
       OBJECT IMPLEMENTS Shape.
           DATA DIVISION.
           WORKING-STORAGE SECTION.
           01  width  USAGE FLOAT-LONG PROPERTY.
           01  height USAGE FLOAT-LONG PROPERTY.
           
           PROCEDURE DIVISION.
           
           IDENTIFICATION DIVISION.
           METHOD-ID. perimeter.
           DATA DIVISION.
           LINKAGE SECTION.
           01  ret USAGE FLOAT-LONG.
           PROCEDURE DIVISION RETURNING ret.
               COMPUTE
                   ret = width * 2.0 + height * 2.0
               END-COMPUTE
               GOBACK.
           END METHOD perimeter.
       
           IDENTIFICATION DIVISION.
           METHOD-ID. shape-area.
           DATA DIVISION.
           LINKAGE SECTION.
           01  ret USAGE FLOAT-LONG.
           PROCEDURE DIVISION RETURNING ret.
               COMPUTE
                   ret = width * height
               END-COMPUTE
               GOBACK.
           END METHOD shape-area.
       
       END OBJECT.
       
       END CLASS Rectangle.

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.

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

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

(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

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

(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

Component Pascal

(* Abstract type *)
Object = POINTER TO ABSTRACT RECORD END;
	
(* Integer inherits Object *)
Integer = POINTER TO RECORD (Object)
	i: INTEGER
END;
(* Point inherits Object *)
Point = POINTER TO RECORD (Object)
	x,y: REAL
END;

...

(* Abstract method of Object *)
PROCEDURE (dn: Object) Show*, NEW, ABSTRACT;
	
(* Implementation of the abstract method Show() in class Integer *)
PROCEDURE (i: Integer) Show*;
BEGIN
	StdLog.String("Integer(");StdLog.Int(i.i);StdLog.String(");");StdLog.Ln
END Show;
	
(* Implementation of the abstract method Show() in class Point *)
PROCEDURE (p: Point) Show*;
BEGIN
	StdLog.String("Point(");StdLog.Real(p.x);StdLog.Char(',');
	StdLog.Real(p.y);StdLog.String(");");StdLog.Ln
END Show;

For usage see tasks Stacks.

Crystal

abstract class Animal # only abstract class can have abstract methods
  abstract def move
  abstract def think

  # abstract class can have normal fields and methods
  def initialize(@name : String)
  end

  def process
    think
    move
  end
end

# WalkingAnimal still have to be declared abstract because `think` was not implemented
abstract class WalkingAnimal < Animal
  def move
    puts "#{@name} walks"
  end
end

class Human < WalkingAnimal
  property in_car = false

  def move
    if in_car
      puts "#{@name} drives a car"
    else
      super
    end
  end

  def think
    puts "#{@name} thinks"
  end
end

# Animal.new # => can't instantiate abstract class
he = Human.new("Andrew") # ok
he.process

Note that "class" can be replaced with "struct" in the above example, because Crystal also supports abstract structs and their inheritance.

D

import std.stdio;

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

interface Bar {
    void bar();

    // Final interface methods are allowed.
    final int spam() { return 1; }
}

class Baz : Foo, Bar { // Super class must come first.
    override void foo() {
        writefln("Meep");
        super.foo();
    }

    void bar() {}
}

void main() {}

Delphi

Abstract Class introduced in Delphi 2006. An abstract class cannot be instantiated and must be derived from in order to be used.

TSomeClass = class abstract (TObject)
  ...
end;


Abstract Methods can only be implemented in derived classes. A concrete class that contains abstract methods can be instantiated. A warning will be generated at compile time, and an EAbstractError exception will thrown if the method is called at run time.

type
  TMyObject = class(TObject)
  public
    procedure AbstractFunction; virtual; abstract; // Your virtual abstract function to overwrite in descendant
    procedure ConcreteFunction; virtual; // Concrete function calling the abstract function
  end;

implementation

procedure TMyObject.ConcreteFunction;
begin
  AbstractFunction; // Calling the abstract function
end;

DWScript

DWScript has both abstract classes and abstract methods.

See Delphi.

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:

interface Foo {
    to bar(a :int, b :int)
}

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

interface Foo guards FooStamp {
    to bar(a :int, b :int)
}

def x implements FooStamp {
    to bar(a :int, b :int) {
        return a - b
    }
}

Eiffel

deferred class 
    AN_ABSTRACT_CLASS

feature

    a_deferred_feature
        -- a feature whose implementation is left to a descendent
        deferred
        end

    an_effective_feature: STRING
        -- deferred (abstract) classes may still include effective features
        do
            Result := "I am implemented!"
        end

end

A more expressive view of an Abstract type in Eiffel:

note
	title: "Prototype Person"
	description: "Abstract notion of a {PERSON}."
	synopsis: "[
		Abstract Data Types as represented by any Eiffel class, fully or partially implemented, are
		not just about the attribute and routine features of the class (deferred or implemented).
		The class and each feature may also have specification rules expressed as preconditions,
		post-conditions, and class invariants. Other assertion contracts may be applied to fully
		implemented features as well.
		
		In the example below, while `age' is deferred (i.e. "abstract"), we have coded a rule which
		states that any caller of `age' must only do so after a `birth_date' has been defined and
		attached to that feature. Failing to do so will cause a contract violation. Moreover, the
		class invariant makes two strong assertions that must always hold for any implemented version
		of {PERSON}: The `birth_date' (if attached--that is--not Void or null) must be in the past
		and never in the future. Also, if "Years" are used to represent the age, the calculation of
		`age' must always agree with "current year - birth year = age".
		
		This form of Abstract Data Type specification has very clear advantages in that not only
		must client code or descendents conform statically, implementing what is deferred, but they
		must also obey the rules of the assertions dynamically in a polymorphic run-time situation.
		]"

deferred class
	PERSON

feature -- Access

	first_name,
	last_name,
	middle_name,
	suffix: STRING

	birth_date: detachable DATE
			-- Date-of-Birth for Current {PERSON}.
		deferred
		end

feature -- Basic Operations

	age: NATURAL_64
			-- Age of Current {PERSON} in some undefined units.
		require
			has_birth_date: attached birth_date
		deferred
		end

	age_units: STRING
			-- Unit-of-Measure (UOM) of `age'.
		attribute
			Result := year_unit_string
		end

	year_unit_string: STRING = "Years"

invariant
	not_future: attached birth_date as al_birth_date implies al_birth_date < (create {DATE}.make_now)
	accurate_age: attached birth_date as al_birth_date and then age > 0 and then age_units.same_string (year_unit_string)
					implies ((create {DATE}.make_now).year - al_birth_date.year) = age

end

Elena

abstract class Bike
{  
    abstract run(); 
}

EMal

Translation of: Go
^|EMal does not support abstract types with partial implementations,
 |but can use interfaces.
 |^
type Beast
interface
  fun getKind ← text by block do end
  fun getName ← text by block do end
  fun getCry ← text by block do end
end
type Dog implements Beast
model
  text kind
  text name
  fun getKind ← text by block do return me.kind end
  fun getName ← text by block do return me.name end
  fun getCry ← text by block do return "Woof" end
end
type Cat implements Beast
model
  text kind
  text name
  fun getKind ← text by block do return me.kind end
  fun getName ← text by block do return me.name end
  fun getCry ← text by block do return "Meow" end
end
type AbstractType
^|Beast b ← Beast() # interface instantiation is not allowed|^
fun bprint ← <Beast b|writeLine(b.getName() +
  ", who's a " + b.getKind() + ", cries: " + b.getCry() + ".")
^|instantiation works because a positional variadic constructor
 |has been auto generated
 |^
var d ← Dog("labrador", "Max")
Cat c ← Cat("siamese", "Sammy")
bprint(d)
bprint(c)
Output:
Max, who's a labrador, cries: Woof.
Sammy, who's a siamese, cries: Meow.

F#

A type with only abstract members and without constructors is an interface (when not marked with the AbstractClass attribute). Example:

type Shape =
  abstract Perimeter: unit -> float
  abstract Area: unit -> float

type Rectangle(width, height) =
  interface Shape with
    member x.Perimeter() = 2.0 * width + 2.0 * height
    member x.Area() = width * height

A type that leaves some or all members unimplemented, is an abstract class. It has to be marked with the AbstractClass attribute. Example:

[<AbstractClass>]
type Bird() =
  // an abstract (=virtual) method with default impl.
  abstract Move : unit -> unit
  default x.Move() = printfn "flying"
  // a pure virtual method
  abstract Sing: unit -> string

type Blackbird() =
  inherit Bird()
  override x.Sing() = "tra-la-la"

type Ostrich() =
  inherit Bird()
  override x.Move() = printfn "walking"
  override x.Sing() = "hiss hiss!"

Fantom

abstract class X
{
  Void method1 ()
  {
    echo ("Method 1 in X")
  }

  abstract Void method2 ()
}

class Y : X
{
  // Y must override the abstract method in X
  override Void method2 ()
  {
    echo ("Method 2 in Y")
  }
}

class Main
{
  public static Void main () 
  {
    y := Y()
    y.method1
    y.method2
  }
}

Forth

Works with: 4tH version 3.61.5
Translation of: Fantom

There are numerous, mutually incompatible object oriented frameworks for Forth. This one works with the FOOS preprocessor extension of 4tH.

include 4pp/lib/foos.4pp

:: X()
   class
     method: method1
     method: method2
   end-class {
     :method { ." Method 1 in X" cr } ; defines method1
   }
;

:: Y()
   extends X()
   end-extends {
     :method { ." Method 2 in Y" cr } ; defines method2
   }
;

: Main
  static Y() y
  y => method1
  y => method2
;

Main

Works with any ANS Forth

Needs the FMS-SI (single inheritance) library code located here: http://soton.mpeforth.com/flag/fms/index.html

include FMS-SI.f

The FMS object extension uses duck typing and so has no need for abstract types.

Fortran

Simple abstract derived type (i.e. abstract class) in Fortran 2008

 
   ! abstract derived type
   type, abstract :: TFigure
      real(rdp) :: area
   contains
      ! deferred method i.e. abstract method =  must be overridden in extended type
      procedure(calculate_area), deferred, pass :: calculate_area
   end type TFigure
   ! only declaration of the abstract method/procedure for TFigure type
   abstract interface
      function  calculate_area(this)
         import TFigure !imports TFigure type from host scoping unit and makes it accessible here
         implicit none
         class(TFigure) :: this
         real(rdp) :: calculate_area
      end function calculate_area
   end interface

FreeBASIC

FreeBASIC does not currently support either abstract types or interfaces as such.

However, you can effectively create an abstract type by declaring all its methods to be abstract, so that they do not require a body in the declaring type itself. Such methods can then be overridden and implemented by its derived types. For example :-

' FB 1.05.0 Win64

Type Animal Extends Object
  Declare Abstract Sub MakeNoise()
End Type

Type Bear Extends Animal
  name As String
  Declare Constructor(name As String)
  Declare Sub MakeNoise() 
End Type

Constructor Bear(name As String)
  This.name = name
End Constructor

Sub Bear.MakeNoise()
  Print name; " is growling"
End Sub

Type Dog Extends Animal
  name As String
  Declare Constructor(name As String)
  Declare Sub MakeNoise() 
End Type

Constructor Dog(name As String)
  This.name = name
End Constructor

Sub Dog.MakeNoise()
  Print name; " is barking"
End Sub

Dim b As Animal Ptr = New Bear("Bruno")
b -> MakeNoise()
Dim d As Animal Ptr = New Dog("Rover")
d -> MakeNoise()
Delete b
Delete d
Print
Print "Press any key to quit program"
Sleep
Output:
Bruno is growling
Rover is barking

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.

class AbstractStack()
   def .valid?(object) nil

tag AbstractStack some-object # always fails

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:

class StackInterface()
   def .valid?(object)
      object
         and
            bound? .enstack
            is-instance? .enstack Closure
            bound? .destack
            is-instance? .destack Closure

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:

class XYZstack(Object)
    def .init()
        var .items ()
    def .enstack(object)
        setq .items (cons object .items)
    def .destack()
        var tmp  (car .items)
        setq .items (cdr .items)
        tmp

Now we can tag an object that conforms to the Interface:

tag StackInterface (XYZstack(.new))

Go

Go's interface type is an abstract type. It defines a set of methods that a concrete type must have to satisfy it.

A variable of an interface type can hold a value of any type that implements the methods that are specified in the interface. You don't need to explicitly "declare" that the type "implements" the interface or anything like that -- the compatibility is purely structural based on the methods.

In the following example, the Dog and Cat types both satisfy the Beast interface because they each have the specified methods. The bprint function can print details for any Beast.

package main

import "fmt"

type Beast interface {
    Kind() string
    Name() string
    Cry() string
}

type Dog struct {
    kind string
    name string
}

func (d Dog) Kind() string { return d.kind }

func (d Dog) Name() string { return d.name }

func (d Dog) Cry() string { return "Woof" }

type Cat struct {
    kind string
    name string
}

func (c Cat) Kind() string { return c.kind }

func (c Cat) Name() string { return c.name }

func (c Cat) Cry() string { return "Meow" }

func bprint(b Beast) {
    fmt.Printf("%s, who's a %s, cries: %q.\n", b.Name(), b.Kind(), b.Cry())
}

func main() {
    d := Dog{"labrador", "Max"}
    c := Cat{"siamese", "Sammy"}
    bprint(d)
    bprint(c)
}
Output:
Max, who's a labrador, cries: "Woof".
Sammy, who's a siamese, cries: "Meow".

Groovy

Translation of: Java

As in Java, methods that are declared but not implemented are called "abstract" methods. An interface is a class-level typing construct that can only contain abstract method declarations (well, and constants, but pay no attention to those).

public interface Interface {
    int method1(double value)
    int method2(String name)
    int add(int a, int b)
}

An abstract class may implement some of its methods and leave others unimplemented. The unimplemented methods and the class itself must be declared "abstract".

public abstract class Abstract1 {
    abstract public int methodA(Date value)
    abstract protected int methodB(String name)
    int add(int a, int b) { a + b }
}

An abstract class may also be used to partially implement an interface. Here class "Abstract2" implements the "add" method from the inherited "Interface", but leaves the other two methods, "method1" and "method2", unimplemented. Abstract methods that an abstract class inherits from an interface or another abstract class do not have to be redeclared.

public abstract class Abstract2 implements Interface {
    int add(int a, int b) { a + b }
}

Interfaces and abstract classes cannot be instantiated directly. There must be a "concrete subclass" that contains a complete implementation in order to instantiate an object.

public class Concrete1 implements Interface {
    public int method1(double value) { value as int }
    public int method2(String name) { (! name) ? 0 : name.toList().collect { it as char }.sum() }
    public int add(int a, int b) { a + b }
}

public class Concrete2 extends Abstract1 {
    public int methodA(Date value) { value.toCalendar()[Calendar.DAY_OF_YEAR] }
    protected int methodB(String name) { (! name) ? 0 : name.toList().collect { it as char }.sum() }
}

public class Concrete3 extends Abstract2 {
    public int method1(double value) { value as int }
    public int method2(String name) { (! name) ? 0 : name.toList().collect { it as char }.sum() }
}

Notice that there are no extra descriptive keywords on the interface method declarations. Interface methods are assumed to be both abstract and public.

Obligatory test:

def c1 = new Concrete1()
assert c1 instanceof Interface
println (new Concrete1().method2("Superman"))

def c2 = new Concrete2()
assert c2 instanceof Abstract1
println (new Concrete2().methodB("Spiderman"))

def c3 = new Concrete3()
assert c3 instanceof Interface
assert c3 instanceof Abstract2
println (new Concrete3().method2("Hellboy"))

Obligatory test output:

843
931
719

Like Java, Groovy does not allow subclasses to inherit from multiple superclasses, even abstract superclasses, but it does let subclasses inherit from multiple interfaces.

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:

class  Eq a  where
   (==) :: a -> a -> Bool
   (/=) :: a -> a -> Bool

Default implementations of the functions can be provided:

class  Eq a  where
   (==) :: a -> a -> Bool
   (/=) :: a -> a -> Bool
   x /= y     =  not (x == y)
   x == y     =  not (x /= y)

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:

func :: (Eq a) => a -> Bool
func x = x == x

Suppose I make a new type

data Foo = Foo {x :: Integer, str :: String}

One could then provide an implementation ("instance") the type class Eq with this type

instance Eq Foo where
   (Foo x1 str1) == (Foo x2 str2) =
      (x1 == x2) && (str1 == str2)

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

Icon and Unicon

Unicon does not distinguish between abstract and concrete classes. An abstract class is a class with abstract methods. Icon is not object-oriented.

class abstraction()
    abstract method compare(l,r) # generates runerr(700, "method compare()")
end

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, but 2 and '2' are very different things.) And allowing user defined types would complicate 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, but nevertheless, the intersections of these domains often enough are not empty.

[In fact, the real motivator for types is the need to allocate finite resources to represent numbers (or whatever else you choose to imagine is being represented). For example: 32 bit integers vs. 64 bit integers vs. 32 bit ieee-854 floating point and 64 bit ieee-854 floating point. Additionally, some operations are sensitive to other details related to these abstractions - the classic examples including overflow vs. carry (add with carry, addition overflow) which depend on the range of numbers involved (2s complement vs. unsigned vs. 1s complement). And then people get carried away trying to "generalize types" rather than "use types" which triggers a need for standardization which mostly means prohibiting some of the most annoying generalizations, which is then followed by other people objecting to those choices... and there is no stopping these trends, which leaves many people fascinated and perhaps horrified at the consequences.]

That said: it's useful to define a type, in the context of J, as "the set of values which may result from a specific parenthesized expression". And, if compilation to machine code is supported, it may also be useful to define constraint mechanisms to be used in expressions, so that machine code may be more easily generated.

(You can find a variety of languages with rather elaborate implementations of types, but as a general rule those elaborate type systems are either (a) inadequate to represent J arrays, or (b) adequate to represent J arrays but with painfully slow implementations for many typical use cases - especially involving large data sets. That said, you can also find cases where these languages perform well - especially if you tailor the problem to the language or vice versa.)

Java

Java has an interface and an abstract class. Neither of which can be instantiated, and require some sort of implementation or abstraction.
For an interface, only the private and default access modifiers are allowed, which also implies they require code.
A private method cannot be overridden by a sub-class, and a default method, optionally, can.
A method with no access modifier is inherently public, must not contain code, and requires implementation by its sub-class.
Member fields are allowed, although are effectively public, final, and static, thus requiring a value.
Here is an example of an interface.

interface Example {
    String stringA = "rosetta";
    String stringB = "code";

    private String methodA() {
        return stringA + " " + stringB;
    }

    default int methodB(int value) {
        return value + 100;
    }

    int methodC(int valueA, int valueB);
}

And here is an example of its implementing class.

class ExampleImpl implements Example {
    public int methodB(int value) {
        return value + 200;
    }

    public int methodC(int valueA, int valueB) {
        return valueA + valueB;
    }
}

The abstract class is very generalized, and for the most part is just a class that allows for un-implemented methods.
The default access modifier is not used here, as it applies only to an interface.
Additionally, if a method is marked abstract, then the private access modifier is not allowed, as the concept does not apply.
Here is an example of an abstract class.
If the class contains abstract methods then the class definition must also have the abstract keyword.

abstract class Example {
    String stringA = "rosetta";
    String stringB = "code";

    private String methodA() {
        return stringA + " " + stringB;
    }

    protected int methodB(int value) {
        return value + 100;
    }

    public abstract int methodC(int valueA, int valueB);
}

Here is an example of a class which extends an abstract class.

class ExampleImpl extends Example {
    public int methodC(int valueA, int valueB) {
        return valueA + valueB;
    }
}

jq

jq does not support abstract types but has a namespace-based module system which can be used to support an "abstract type" approach of programming, as illustrated here using an extension of the Beast/Cat/Dog example.

The following is tailored to the C implementation of jq but could also be adapted for the Go implementation.

def Beast::new($kind; $name): {
   superclass: "Beast",
   class: null,
   $kind,
   $name,
   cry: "unspecified"
};   

def Ape::new($kind; $name):
  Beast::new($kind; $name)
  | .class = "Ape"
  | .cry = "Hoot";

def Cat::new($kind; $name):
  Beast::new($kind; $name)
  | .class = "Cat"
  | .cry = "Meow";

def Dog::new($kind; $name):
  Beast::new($kind; $name)
  | .class = "Dog"
  | .cry = "Woof";


def print:
  def a($noun):
    $noun
    | if .[0:1] | test("[aeio]") then "an \(.)" else "a \(.)" end;

  if .class == null
  then "\(.name) is \(a(.kind)), which is an unknown type of \(.superclass)."
  else "\(.name) is \(a(.kind)), a type of \(.class), and cries: \(.cry)."
  end;

Beast::new("sasquatch"; "Bigfoot"),
Ape::new("chimpanzee"; "Nim Chimsky"),
Dog::new("labrador"; "Max"),
Cat::new("siamese"; "Sammy") 
| print
Output:
Bigfoot is a sasquatch, which is an unknown type of Beast.
Nim Chimsky is a chimpanzee, a type of Ape, and cries: Hoot.
Max is a labrador, a type of Dog, and cries: Woof.
Sammy is a siamese, a type of Cat, and cries: Meow.

Julia

Abstract types cannot be instantiated, and serve only as nodes in the type graph, thereby describing sets of related concrete types: those concrete types which are their descendants.

Usage:

abstract type «name» end
abstract type «name» <: «supertype» end

Examples:

abstract type Number end
abstract type Real          <: Number end
abstract type FloatingPoint <: Real end
abstract type Integer       <: Real end
abstract type Signed        <: Integer end
abstract type Unsigned      <: Integer end

See more [1]

Kotlin

Kotlin supports abstract classes and interfaces, both of which can contain non-abstract members. The basic difference between them is that interfaces cannot store state.

Here's a very simple (and silly) example of both:

// version 1.1

interface Announcer {
    fun announceType()

    // interface can contain non-abstract members but cannot store state
    fun announceName() {
        println("I don't have a name")
    }
}

abstract class Animal: Announcer {
    abstract fun makeNoise()

    // abstract class can contain non-abstract members
    override fun announceType() {
        println("I am an Animal")
    }
}

class Dog(private val name: String) : Animal() {
    override fun makeNoise() {
       println("Woof!")
    }

    override fun announceName() {
       println("I'm called $name")
    }
}

class Cat: Animal() {
    override fun makeNoise() {
       println("Meow!")
    }

    override fun announceType() {
       println("I am a Cat")
    }
}

fun main(args: Array<String>) {
    val d = Dog("Fido")
    with(d) {
        makeNoise()
        announceType()  // inherits Animal's implementation
        announceName()
    }
    println()
    val c = Cat()
    with(c) {
        makeNoise()
        announceType()
        announceName()  // inherits Announcer's implementation
   }
}
Output:
Woof!
I am an Aninal
I'm called Fido

Meow!
I am a Cat
I don't have a name

Lasso

Instead of abstract classes or interfaces, Lasso uses a trait system.

define abstract_trait => trait {
    require get(index::integer)
    
    provide first()  => .get(1)
    provide second() => .get(2)
    provide third()  => .get(3)
    provide fourth() => .get(4)
}

define my_type => type {
    parent array
    trait { import abstract_trait }

    public onCreate(...) => ..onCreate(:#rest)
}

local(test) = my_type('a','b','c','d','e')
#test->first  + "\n"
#test->second + "\n"
#test->third  + "\n"
#test->fourth + "\n"
Output:
a
b
c
d

Lingo

As weakly typed script language, Lingo does not support any sort of inheritance control at compile time. But you can implement something similar to abstract classes and interfaces as user-defined code, by preventing (and optionally showing error messages) any class instantiations that don't fit to the intended scheme.

Abstract Classes

In some movie script:

on extendAbstractClass (instance, abstractClass)
  -- 'raw' instance of abstract class is made parent ("ancestor") of the 
  -- passed instance, i.e. the passed instance extends the abstract class
  instance.setProp(#ancestor, abstractClass.rawNew())
end

Parent script "AbstractClass":

-- instantiation of abstract class by calling its constructor fails
on new (me)
  -- optional: show error message as alert
  _player.alert("Error:"&&me.script&&" is an abstract class")
  return VOID
end

on ring (me, n)
  repeat with i = 1 to n
    put me.ringtone
  end repeat
end

Parent script "MyClass"

property ringtone

on new (me)
  extendAbstractClass(me, script("AbstractClass"))
  me.ringtone = "Bell"
  return me
end

on foo (me)
  put "FOO"
end

Usage:

obj = script("MyClass").new()
obj.ring(3)
-- "Bell"
-- "Bell"
-- "Bell"

-- this fails
test = script("AbstractClass").new()
put test
-- <Void>

Interfaces

In some movie script:

on implementsInterface (instance, interfaceClass)
  interfaceFuncs = interfaceClass.handlers()
  funcs = instance.handlers()
  repeat with f in interfaceFuncs
    if funcs.getPos(f)=0 then
      -- optional: show error message as alert
      _player.alert("Error:"&&instance.script&&"doesn't implement interface"&&interfaceClass)
      return FALSE
    end if
  end repeat
  return TRUE
end

Parent script "InterfaceClass": (Note: in Lingo closing function definitions with "end" is optional, so this a valid definition of 3 empty functions)

on foo
on bar
on foobar

Parent script "MyClass":

on new (me)
  -- if this class doesn't implement all functions of the 
  -- interface class, instantiation fails
  if not implementsInterface(me, script("InterfaceClass")) then
    return VOID
  end if
  return me
end

on foo (me)
  put "FOO"
end

on bar (me)
  put "BAR"
end

on foobar (me)
  put "FOOBAR"
end

Usage:

obj = script("MyClass").new()
put obj -- would show <Void> if interface is not fully implemented
-- <offspring "MyClass" 2 171868>

Logtalk

In Logtalk, methods (predicates) must be declared but their definition is not mandatory. Being a logic-based language and making use of the closed-world assumption, invoking a method that is declared but not defined simply fails. If necessary, is trivial to define a method such that it throws an exception. Moreover, Logtalk doesn't define an "abstract" or "virtual" keyword. Instead it uses an operational definition where e.g. a class is considered abstract if it doesn't provide a method for creating new instances.

Logtalk supports the definition of interfaces (protocols), which can contain public, protected, and private declarations of methods (predicates). In addition, an object can qualify an implements relation with an interface (protocol) using the keywords "public", "protected", and "private".

:- protocol(datep).

    :- public(today/3).
    :- public(leap_year/1).
    :- public(name_of_day/3).
    :- public(name_of_month/3).
    :- public(days_in_month/3).

:- end_protocol.

Lua

Lua does not include built-in object oriented paradigms. These features can be added using simple code such as the following:

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 instantiated")
    end

    if not baseClass then baseClass = BaseClass end
        setmetatable( new_class, { __index = baseClass } )

    return new_class
end

BaseClass.class = class
BaseClass.abstractClass = abstractClass

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 instantiate it. Example:

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

M2000 Interpreter

M2000 not use interfaces, but can combine groups (used as objects), and because we can alter definitions, we can make an Abstract group by implement modules and functions with a call to Error "not implement yet"

Class BaseState {
Private:
      x as double=1212, z1 as currency=1000, k$="ok"
      Module Err {
                  Module "Class.BaseState"
                  Error "not implement yet"
      }      
}
Class AbstractOne {
Public:
      Group z {
            Value {
                  Link parent z1 to z1
                  =z1
            }
      }
      Function M(k as double) {
            .Err
      }
      Module AddCurrency (k as currency) {
            .Err
      }
      Function GetString$ {
            .Err
      } 
Class:
      Module AbstractOne {
                  If Not Match("G") Then Exit
                  Read x
                  \\ combine x with This
                  This=x
      }
}
\\ create new group as K
K=AbstractOne(BaseState())
Try  ok {
      Print K.GetString$()
}
If Not ok Then Print Error$
\\ Now Add final functions/modules
Group k {
      Function Final M(k as double) {
            =.x*k
      }
      Module Final AddCurrency (k as currency) {
            .z1+=k
      }
      Function Final GetString$ {
            =.K$
      }       
}
Print k.M(100), k.GetString$()
K.AddCurrency 50.12
Def ExpType$(x)=Type$(x)
Print k.z=1050.12, ExpType$(k.z), Type$(k.z) ' true, Currency, Group
\\ Now combine AbstractOne without new BaseState
\\ but because all functions are final in k, nothing combined
k=AbstractOne()
Print k.M(100), k.GetString$()
For k {
      \\ we can use For Object {} and a dot before members to get access
      Print .z=1050.12, ExpType$(.z), Type$(.z) ' true, Currency, Group
}

Mathematica /Wolfram Language

Mathematica is a symbolic language and as such does not support traditional object oriented design patterns. However, it is quite easy to define pseudo-interfaces that depend on an object implementing a set of functions:

(* Define an interface, Foo, which requires that the functions Foo, Bar, and Baz be defined *)
InterfaceFooQ[obj_] := ValueQ[Foo[obj]] && ValueQ[Bar[obj]] && ValueQ[Baz[obj]];
PrintFoo[obj_] := Print["Object ", obj, " does not implement interface Foo."];
PrintFoo[obj_?InterfaceFooQ] := Print[
   "Foo: ", Foo[obj], "\n",
   "Bar: ", Bar[obj], "\n",
   "Baz: ", Baz[obj], "\n"];

(* Extend all integers with Interface Foo *)
Foo[x_Integer] := Mod[x, 2];
Bar[x_Integer] := Mod[x, 3];
Baz[x_Integer] := Mod[x, 5];

(* Extend a particular string with Interface Foo *)
Foo["Qux"] = "foo";
Bar["Qux"] = "bar";
Baz["Qux"] = "baz";

(* Print a non-interface object *)
PrintFoo[{"Some", "List"}];
(* And for an integer *)
PrintFoo[8];
(* And for the specific string *)
PrintFoo["Qux"];
(* And finally a non-specific string *)
PrintFoo["foobarbaz"]
Output:
Object {Some,List} does not implement interface Foo.

Foo: 0
Bar: 2
Baz: 3

Foo: foo
Bar: bar
Baz: baz

Object foobarbaz does not implement interface Foo.

Note that, in this implementation, the line between interface and abstract type is blurred. It could be argued that PrintFoo[] is a concrete member of the abstract type InterfaceFoo, or that it's a separate function that accepts anything implementing the interface InterfaceFoo.

MATLAB

Abstract Class
classdef (Abstract) AbsClass 
   ...
end

For classes that declare the Abstract class attribute:

  • Concrete subclasses must redefine any properties or methods that are declared as abstract.
  • The abstract class does not need to define any abstract methods or properties.

When you define any abstract methods or properties, MATLAB® automatically sets the class Abstract attribute to true.

Abstract Methods
methods (Abstract)
   abstMethod(obj)
end

For methods that declare the Abstract method attribute:

  • Do not use a function...end block to define an abstract method, use only the method signature.
  • Abstract methods have no implementation in the abstract class.
  • Concrete subclasses are not required to support the same number of input and output arguments and do not need to use the same argument names. However, subclasses generally use the same signature when implementing their version of the method.
Abstract Properties
properties (Abstract)
   AbsProp
end

For properties that declare the Abstract property attribute:

  • Concrete subclasses must redefine abstract properties without the Abstract attribute.
  • Concrete subclasses must use the same values for the SetAccess and GetAccess attributes as those attributes used in the abstract superclass.
  • Abstract properties cannot define access methods and cannot specify initial values. The subclass that defines the concrete property can create access methods and specify initial values.

Mercury

Translation of: Haskell

'Abstract type' in Mercury's parlance is just a type that appears in the interface of a module but which is only defined in the implementation of the module, a form of information hiding.

However, in the meaning of this task, Mercury has 'abstract types' in its typeclasses. For example, the following implements an 'eq' typeclass, a predicate that works for any instance of this typeclass, and a type that's an instance of this typeclass.

This module differs from the Haskell in two respects: first, Mercury can't provide default implementations; and second, this isn't a built-in typeclass. Mercury lacks Haskell's Eq, Ord, Show, and Read typeclasses, instead having these features by default for all tpyes.

:- module eq.
:- interface.

:- typeclass eq(T) where [
    pred (T::in) == (T::in) is semidet,
    pred (T::in) \= (T::in) is semidet
].

:- pred f(T::in) is semidet <= eq(T).

:- type foo
    --->    foo(
                x :: int,
                str :: string
            ).

:- instance eq(foo).

:- implementation.

f(X) :- X == X.

:- instance eq(foo) where [
    A == B :- (A^x = B^x, A^str = B^str),
    A \= B :- not A == B
].

Nemerle

using System.Console;

namespace RosettaCode
{
    abstract class Fruit
    {
        abstract public Eat() : void;
        abstract public Peel() : void;
        
        virtual public Cut() : void      // an abstract class con contain a mixture of abstract and implemented methods
        {                                // the virtual keyword allows the method to be overridden by derivative classes
            WriteLine("Being cut.");
        }
    }
    
    interface IJuiceable
    {
        Juice() : void;           // interfaces contain only the signatures of methods
    }
    
    class Orange : Fruit, IJuiceable
    {
        public override Eat() : void     // implementations of abstract methods need to be marked override
        {
            WriteLine("Being eaten.");
        }
        
        public override Peel() : void
        {
            WriteLine("Being peeled.");
        }
        
        public Juice() : void
        {
            WriteLine("Being juiced.");
        }
    }
}

NetRexx

/* NetRexx */
options replace format comments java crossref symbols binary

-- -----------------------------------------------------------------------------
class RCAbstractType public final

method main(args = String[]) public constant

  say '  Testing' RCAbstractType.class.getSimpleName
  say '  Creating an object of type:' Concrete.class.getSimpleName
  conk = Concrete()
  say    'getClassName:'.right(20) conk.getClassName
  say    'getIfaceName:'.right(20) conk.getIfaceName
  say   'mustImplement:'.right(20) conk.mustImplement
  say    'canOverride1:'.right(20) conk.canOverride1
  say    'canOverride2:'.right(20) conk.canOverride2
  say 'callOverridden2:'.right(20) conk.callOverridden2

  return

-- -----------------------------------------------------------------------------
class RCAbstractType.Iface interface

ifaceName = RCAbstractType.Iface.class.getSimpleName

method getIfaceName() public returns String
method canOverride1() public returns String
method canOverride2() public returns String

-- -----------------------------------------------------------------------------
class RCAbstractType.Abstraction abstract implements RCAbstractType.Iface

properties inheritable
  className = String

method Abstraction() public
  setClassName(this.getClass.getSimpleName)
  return

method mustImplement() public abstract returns String

method getClassName() public returns String
  return className

method setClassName(nm = String) public
  className = nm
  return

method getIfaceName() public returns String
  return RCAbstractType.Iface.ifaceName

method canOverride1() public returns String
  return 'In' RCAbstractType.Abstraction.class.getSimpleName'.canOverride1'

method canOverride2() public returns String
  return 'In' RCAbstractType.Abstraction.class.getSimpleName'.canOverride2'

-- -----------------------------------------------------------------------------
class RCAbstractType.Concrete extends RCAbstractType.Abstraction

method Concrete() public
  super()
  return

method mustImplement() public returns String
  return 'In' RCAbstractType.Concrete.class.getSimpleName'.mustImplement'

method canOverride2() public returns String
  return 'In' RCAbstractType.Concrete.class.getSimpleName'.canOverride2'

method callOverridden2() public returns String
  return super.canOverride2
Output
  Testing RCAbstractType
  Creating an object of type: Concrete
       getClassName: Concrete
       getIfaceName: Iface
      mustImplement: In Concrete.mustImplement
       canOverride1: In Abstraction.canOverride1
       canOverride2: In Concrete.canOverride2
    callOverridden2: In Abstraction.canOverride2

newLISP

; file:   abstract.lsp
; url:    http://rosettacode.org/wiki/Abstract_type
; author: oofoe 2012-01-28

; Abstract Shape Class

(new Class 'Shape)     ; Derive new class.

(define (Shape:Shape   ; Shape constructor.
         (pen "X"))    ; Default value.
  (list (context)      ; Assemble data packet.
        (list 'pen pen) 
        (list 'size (args))))

(define (Shape:line x) ; Print out row with 'pen' character.
  (dotimes (i x) 
    (print (lookup 'pen (self)))) 
  (println))

(define (Shape:draw))  ; Placeholder, does nothing.

; Derived Objects

(new Shape 'Box)

(define (Box:draw)     ; Override base draw method.
  (let ((s (lookup 'size (self))))
    (dotimes (i (s 0)) (:line (self) (s 0)))))

(new Shape 'Rectangle)

(define (Rectangle:draw)
  (let ((size (lookup 'size (self))))
    (dotimes (i (size 1)) (:line (self) (size 0)))))

; Demonstration

(:draw (Shape))        ; Nothing happens. 

(println "A box:")
(:draw (Box "O" 5))    ; Create Box object and call draw method.

(println "\nA rectangle:")
(:draw (Rectangle "R" 32 4))

(exit)

Sample output:

A box:
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO

A rectangle:
RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR

Nim

In Nim type classes can be seen as an abstract type. Type classes specify interfaces, which can be instantiated by concrete types.

type
  Comparable = concept x, y
    (x < y) is bool
  
  Stack[T] = concept s, var v
    s.pop() is T
    v.push(T)
    
    s.len is Ordinal
    
    for value in s:
      value is T

Nit

Source: the official Nit’s repository

# Task: abstract type
#
# Methods without implementation are annotated `abstract`.
#
# Abstract classes and interfaces can contain abstract methods and concrete (i.e. non-abstract) methods.
# Abstract classes can also have attributes.
module abstract_type

interface Inter
	fun method1: Int is abstract
	fun method2: Int do return 1
end

abstract class Abs
	fun method1: Int is abstract
	fun method2: Int do return 1
	var attr: Int
end

Oberon-2

Works with: oo2c Version 2
TYPE
  Animal = POINTER TO AnimalDesc;
  AnimalDec = RECORD [ABSTRACT] END;

  (* Cat inherits from Animal *)
  Cat = POINTER TO CatDesc;
  CatDesc = RECORD (AnimalDesc) END;

Objeck

class ClassA {
   method : virtual : public : MethodA() ~ Int;
 
   method : public : MethodA() ~ Int {
      return 0;
   }
}

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:

class virtual foo =
  object
    method virtual bar : int
  end

Abstract Type

In OCaml what we call an abstract type is not OO related, it is only a type defined without definition, for example:

type t

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:

module Foo : sig
  type t
end = struct
  type t = int * int
end

Pure abstract types in the implementation:

type u
type v
type 'a t
type ut = u t
type vt = v t

Oforth

Oforth properties implement abstract types.

Classes have only one parent, but can have multiple properties.

Unlike interfaces, properties can include method implementations and attributes (see lang/Comparable.of for instance).

Property new: Spherical(r)
Spherical method: radius  @r ;
Spherical method: setRadius  := r ;
Spherical method: perimeter  @r 2 * PI * ;
Spherical method: surface   @r sq PI * 4 * ;

Object Class new: Ballon(color)
Ballon is: Spherical 
Ballon method: initialize(color, r)  color := color self setRadius(r) ;

Object Class new: Planete(name)
Planete is: Spherical 
Planete method: initialize(n, r)  n := name self setRadius(r) ;

Usage :

: testProperty
| b p |
   Ballon new($red, 0.1) ->b
   System.Out "Ballon radius    is : " << b radius << cr
   System.Out "Ballon perimeter is : " << b perimeter << cr
   System.Out "Ballon surface   is : " << b surface << cr

   Planete new("Earth", 6371000.0) ->p
   System.Out "Earth radius    is : " << p radius << cr
   System.Out "Earth perimeter is : " << p perimeter << cr
   System.Out "Earth surface   is : " << p surface << cr 
;
Output:
Ballon radius    is : 0.1
Ballon perimeter is : 0.628318530717959
Ballon surface   is : 0.125663706143592
Earth radius    is : 6371000
Earth perimeter is : 40030173.5920411
Earth surface   is : 510064471909788

ooRexx

Interface

  -- Example showing a class that defines an interface in ooRexx
  -- shape is the interface class that defines the methods a shape instance
  -- is expected to implement as abstract methods.  Instances of the shape
  -- class need not directly subclass the interface, but can use multiple
  -- inheritance to mark itself as implementing the interface.

  r=.rectangle~new(5,2)
  say r
  -- check for instance of
  if r~isa(.shape) then say "a" r~name "is a shape"
  say "r~area:" r~area
  say

  c=.circle~new(2)
  say c
  -- check for instance of shape works even if inherited
  if c~isa(.shape) then say "a" c~name "is a shape"
  say "c~area:" c~area
  say

  -- a mixin is still a class and can be instantiated.  The abstract methods
  -- will give an error if invoked
  g=.shape~new
  say g
  say g~name
  say "g~area:" g~area -- invoking abstract method results in a runtime error.

  -- the "MIXINCLASS" tag makes this avaiable for multiple inhertance
  ::class shape MIXINCLASS Object
    ::method area abstract
    ::method name abstract

  -- directly subclassing the the interface
  ::class rectangle subclass shape

    ::method init
      expose length width
      use strict arg length=0, width=0

    ::method area
      expose length width
      return length*width

    ::method name
      return "Rectangle"

  -- inherits the shape methods
  ::class circle subclass object inherit shape

    ::method init
      expose radius
      use strict arg radius=0

    ::method area
      expose radius
      numeric digits 20
      return radius*radius*3.14159265358979323846

    ::method name
      return "Circle"
Output:
a RECTANGLE
a Rectangle is a shape
r~area: 10

a CIRCLE
a Circle is a shape
c~area: 12.566370614359172954

a SHAPE
    25 *-* say g~name
Error 93 running E:\ifa.rex line 25:  Incorrect call to method.
Error 93.965:  Method NAME is ABSTRACT and cannot be directly invoked.

Abstract Type

  -- Example showing an abstract type in ooRexx                         
  -- shape is the abstract class that defines the abstract method area   
  -- which is then implemented by its two subclasses, rectangle and circle
  -- name is the method inherited by the subclasses.                    
  -- author:         Rony G. Flatscher, 2012-05-26
  -- changed/edited: Walter Pachl, 2012-05-28 28 
  -- highlighting:   to come 

  r=.rectangle~new(5,2)
  say r
  say r~name
  say "r~area:" r~area
  say

  c=.circle~new(2)
  say c
  say c~name
  say "c~area:" c~area
  say

  g=.shape~new
  say g
  say g~name
  say "g~area:" g~area -- invoking abstract method results in a runtime error.

  ::class shape
    ::method area abstract
    ::method name
      return "self~class~id:" self~class~id


  ::class rectangle subclass shape

    ::method init
      expose length width
      use strict arg length=0, width=0

    ::method area
      expose length width
      return length*width

  ::class circle subclass shape

    ::method init
      expose radius
      use strict arg radius=0

    ::method area
      expose radius
      numeric digits 20
      return radius*radius*3.14159265358979323846
Output:
a RECTANGLE
self~class~id: RECTANGLE
r~area: 10

a CIRCLE
self~class~id: CIRCLE
c~area: 12.566370614359172954

a SHAPE
self~class~id: SHAPE
    24 *-* say "g~area:" g~area -- invoking abstract method results in a runtime error.
Error 93 running E:\aty.rex line 24:  Incorrect call to method.
Error 93.965:  Method AREA is ABSTRACT and cannot be directly invoked.

OxygenBasic


'ABSTRACT TYPES EXAMPLE
'PARTICLES

type position {}
type angle    {}
type velocity {}
type mass     {}
type counter  {}

type particle
  position p
  angle    a
  velocity v
  mass     m
end type

class particles
  particle*q
  counter c
  method constructor (){}
  method destructor  (){}
  method action      (){}
end class

Oz

Translation of: Python

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

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

PARI/GP

GP is not object-oriented and cannot sensibly use abstract types. PARI can use the same solution as C.

Pascal and Object Pascal

In ObjectPascal mode FreePascal has classes and abstract methods.

See Delphi


PascalABC.NET

type 
  MyAbstract = abstract class
    public
      procedure Proc1; abstract;
      procedure Proc2;
      begin
      end;
  end;
  MyClass = class(MyAbstract)
    public
      procedure Proc1; override;
      begin
      end;
  end;
  

begin
  var a := new MyClass;
  a.Proc1;
end.

Abstract method is a virtual method. You must overload it in a subclass using an override modifier.

It is also possible to define an interface and class, implementing this interface:

type 
  IMyInterface = interface
    procedure Proc1;
    procedure Proc2;
  end;
  MyClass = class(IMyInterface)
    public
      procedure Proc1;
      begin
        Print(1);
      end;
      procedure Proc2;
      begin
        Print(2);
      end;
  end;

begin
  var a: IMyInterface := new MyClass;
  a.Proc1;
  a.Proc2;
end.

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;

Since Perl 5.12, the Yadda Yadda operator (...) dies with an Unimplemented error,

package AbstractFoo;
 
use strict;
 
sub frob { ... }
sub baz { ... }
 
sub frob_the_baz {
    my $self = shift;
    $self->frob($self->baz());
}

1;

Raku inspired roles are provided by the Moose library

package AbstractFoo;

use Moose::Role;

requires qw/frob baz/;

sub frob_the_baz {
    my $self = shift;
    $self->frob($self->baz());
}

1;

Roles are also provided in a more lightweight form with Role::Tiny library

package AbstractFoo;

use Role::Tiny;

requires qw/frob baz/;

sub frob_the_baz {
    my $self = shift;
    $self->frob($self->baz());
}

1;

Phix

Library: Phix/Class

In many senses the object type is a completely abstract type, since it can hold anything, from native integers to class instances.

You can also have explicitly abstract classes (and/or abstract methods). Needs 0.8.1+

abstract class job
    integer id
--  procedure test(); -- (the ; makes it an abstract method)
    procedure show()
        printf(1,"this is job:%d\n",id)
    end procedure
end class
--job j = new({1})  -- compilation error: "abstract class"
 
class errand extends job
end class
errand e = new({2}) 
e.show()
Output:
this is job:2

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

abstract class Abs {
	abstract public function method1($value);
	abstract protected function method2($name);
	function add($a, $b){
		return a + b;
	}
}

Interfaces in PHP may not implement any methods and all methods are public and implicitly abstract.

interface Inter {
	public function method1($value);
	public function method2($name);
	public function add($a, $b);
}

PicoLisp

# In PicoLisp there is no formal difference between abstract and concrete classes.
# There is just a naming convention where abstract classes start with a
# lower-case character after the '+' (the naming convention for classes).
# This tells the programmer that this class has not enough methods
# defined to survive on its own.
   
(class +abstractClass)
   
(dm someMethod> () 
   (foo)
   (bar) )

PowerShell

#Requires -Version 5.0 

Class Player
{
  <#
    Properties: Name, Team, Position and Number
  #>
    [string]$Name

    [ValidateSet("Baltimore Ravens","Cincinnati Bengals","Cleveland Browns","Pittsburgh Steelers",
                 "Chicago Bears","Detroit Lions","Green Bay Packers","Minnesota Vikings",
                 "Houston Texans","Indianapolis Colts","Jacksonville Jaguars","Tennessee Titans",
                 "Atlanta Falcons","Carolina Panthers","New Orleans Saints","Tampa Bay Buccaneers",
                 "Buffalo Bills","Miami Dolphins","New England Patriots","New York Jets",
                 "Dallas Cowboys","New York Giants","Philadelphia Eagles","Washington Redskins",
                 "Denver Broncos","Kansas City Chiefs","Oakland Raiders","San Diego Chargers",
                 "Arizona Cardinals","Los Angeles Rams","San Francisco 49ers","Seattle Seahawks")]
    [string]$Team

    [ValidateSet("C","G","T","QB","RB","WR","TE","DT","DE","ILB","OLB","CB","S","K","H","LS","P","KOS","R")]
    [string]$Position

    [ValidateRange(0,99)]
    [int]$Number

  <#
    Constructor: Creates a new Player object, with the specified Name, Team, Position and Number.
  #>
    Player([string]$Name, [string]$Team, [string]$Position, [int]$Number)
    {
        $this.Name     = (Get-Culture).TextInfo.ToTitleCase("$Name")
        $this.Team     = (Get-Culture).TextInfo.ToTitleCase("$Team")
        $this.Position = $Position.ToUpper()
        $this.Number   = $Number
    }

  <#
    Methods: Trade the player to a different team (optional parameters for methods in PowerShell 5 classes are not available.  Boo!!)
             An overloaded method is a method with the same name as another method but in a different context,
             in this case with different parameters.
  #>
    Trade([string]$NewTeam)
    {
        [string[]]$league = "Baltimore Ravens","Cincinnati Bengals","Cleveland Browns","Pittsburgh Steelers",
                            "Chicago Bears","Detroit Lions","Green Bay Packers","Minnesota Vikings",
                            "Houston Texans","Indianapolis Colts","Jacksonville Jaguars","Tennessee Titans",
                            "Atlanta Falcons","Carolina Panthers","New Orleans Saints","Tampa Bay Buccaneers",
                            "Buffalo Bills","Miami Dolphins","New England Patriots","New York Jets",
                            "Dallas Cowboys","New York Giants","Philadelphia Eagles","Washington Redskins",
                            "Denver Broncos","Kansas City Chiefs","Oakland Raiders","San Diego Chargers",
                            "Arizona Cardinals","Los Angeles Rams","San Francisco 49ers","Seattle Seahawks"

        if ($NewTeam -in $league | Where-Object {$_ -notmatch $this.Team})
        {
            $this.Team = (Get-Culture).TextInfo.ToTitleCase("$NewTeam")
        }
        else
        {
            throw "Invalid Team"
        }
    }

    Trade([string]$NewTeam, [int]$NewNumber)
    {
        [string[]]$league = "Baltimore Ravens","Cincinnati Bengals","Cleveland Browns","Pittsburgh Steelers",
                            "Chicago Bears","Detroit Lions","Green Bay Packers","Minnesota Vikings",
                            "Houston Texans","Indianapolis Colts","Jacksonville Jaguars","Tennessee Titans",
                            "Atlanta Falcons","Carolina Panthers","New Orleans Saints","Tampa Bay Buccaneers",
                            "Buffalo Bills","Miami Dolphins","New England Patriots","New York Jets",
                            "Dallas Cowboys","New York Giants","Philadelphia Eagles","Washington Redskins",
                            "Denver Broncos","Kansas City Chiefs","Oakland Raiders","San Diego Chargers",
                            "Arizona Cardinals","Los Angeles Rams","San Francisco 49ers","Seattle Seahawks"

        if ($NewTeam -in $league | Where-Object {$_ -notmatch $this.Team})
        {
            $this.Team = (Get-Culture).TextInfo.ToTitleCase("$NewTeam")
        }
        else
        {
            throw "Invalid Team"
        }

        if ($NewNumber -in 0..99)
        {
            $this.Number = $NewNumber
        }
        else
        {
            throw "Invalid Number"
        }
    }
}

Create a new player:

$player1 = [Player]::new("sam bradford", "philadelphia eagles", "qb", 7)
$player1
Output:
Name         Team                Position Number
----         ----                -------- ------
Sam Bradford Philadelphia Eagles QB            7

Trade the player:

$player1.Trade("minnesota vikings", 8)
$player1
Output:
Name         Team                Position Number
----         ----                -------- ------
Sam Bradford Minnesota Vikings   QB            8

Create a new player:

$player2 = [Player]::new("demarco murray", "philadelphia eagles", "rb", 29)
$player2
Output:
Name           Team                Position Number
----           ----                -------- ------
Demarco Murray Philadelphia Eagles RB           29

Trade the player:

$player2.Trade("tennessee titans")
$player2
Output:
Name           Team             Position Number
----           ----             -------- ------
Demarco Murray Tennessee Titans RB           29

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,

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

Starting from Python 2.6, abstract classes can be created using the standard abc module:

from abc import ABCMeta, abstractmethod

class BaseQueue():
    """Abstract Class 
    """
    __metaclass__ = ABCMeta

    def __init__(self):
        self.contents = list()

    @abstractmethod
    def Enqueue(self, item):
        pass

    @abstractmethod
    def Dequeue(self):
        pass

    def Print_Contents(self):
        for i in self.contents:
            print i,

Racket

#lang racket

(define animal-interface (interface () say))

(define cat% (class* object% (animal-interface) (super-new))) ;; error

(define cat% (class* object% (animal-interface)
               (super-new)
               (define/public (say)
                 (display "meeeeew!"))))

(define tom (new cat%))
(send tom say)

Raku

(formerly Perl 6)

Works with: rakudo version 2015.12

Raku supports roles, which are a bit like interfaces, but unlike interfaces in Java they can also contain some implementation.

use v6;

role A {
    # must be filled in by the class it is composed into
    method abstract() { ... };

    # can be overridden in the class, but that's not mandatory
    method concrete() { say '# 42' };
}

class SomeClass does A {
    method abstract() {
        say "# made concrete in class"
    }
}

my $obj = SomeClass.new;
$obj.abstract();
$obj.concrete();

# output:
# made concrete in class
# 42

REBOL

REBOL [
	Title: "Abstract Type"
	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

Red

Red [
  Title: "Abstract Type"
  Original-Author: oofoe
]

; 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 newline]
  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.

print "An abstract shape (nothing):"
s: make shape []                s/draw ; Nothing happens.

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

print [newline "A rectangle:"]
r: make rectangle [size: 32x5]  r/draw

ReScript

Here is an abstract type definition:

type t

REXX

(This entry modeled after the J entry.)

(Classic) REXX does not support abstract types   (as defined here on this task page).
REXX supports a character type, and as such, nothing needs to be declared.

Ruby

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

Library: RubyGems

package called abstraction exists where:

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

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

Rust

Rust doesn't have traditional object oriented concepts such as classes, instead it uses a concept called traits. Traits are similar to abstract classes in the sense that they define an interface a struct must conform to. A trait can be defined as such:

trait Shape {
    fn area(self) -> i32;
}

The trait can then be implemented on a struct.

struct Square {
    side_length: i32
}

impl Shape for Square {
    fn area(self) -> i32 {
        self.side_length * self.side_length
    }
}

Note, traits can also have a default implementation:

trait Shape {
    fn area(self) -> i32;

    fn is_shape(self) -> bool {
        true
    }
}

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:

abstract class X {
  type A
  var B: A
  val C: A
  def D(a: A): A
}

trait Y {
  val x: X
}

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

Seed7

The object orientation of Seed7 is based on inteface types. An abstract type consists of an interface type and interface functions, that use the interface. Interface (DYNAMIC) functions describe what can be done with objects of an interface type. Seed7 functions are freestanding and don't have an implicit this (or self) parameter. This concept allows multiple dispatch. Instead of an implicit this parameter an interface function has a parameter of an interface type. A function is automaticall attached to the interface, when it has an parameter of the interface type.

const type: myInterf is sub object interface;

const func integer: method1 (in myInterf: interf, in float: aFloat) is DYNAMIC;
const func integer: method2 (in myInterf: interf, in string: name) is DYNAMIC;
const func integer: add (in myInterf: interf, in integer: a, in integer: b) is DYNAMIC;

Sidef

Translation of: Raku
class A {
    # must be filled in by the class which will inherit it
    method abstract() { die 'Unimplemented' };

    # can be overridden in the class, but that's not mandatory
    method concrete() { say '# 42' };
}

class SomeClass << A {
    method abstract() {
        say "# made concrete in class"
    }
}

var obj = SomeClass.new;
obj.abstract();   # made concrete in class
obj.concrete();   # 42

Simula

Abtract Datatypes are declared using the VIRTUAL keyword. For example, we need the following two procedures hash and equalto for a hash map implementation.

    ! ABSTRACT HASH KEY TYPE ;
    LISTVAL CLASS HASHKEY;
    VIRTUAL:
        PROCEDURE HASH IS
            INTEGER PROCEDURE HASH;;
        PROCEDURE EQUALTO IS
            BOOLEAN PROCEDURE EQUALTO(K); REF(HASHKEY) K;;
    BEGIN
    END HASHKEY;

A concrete implementation can be derived as follows:

    ! COMMON HASH KEY TYPE IS TEXT ;
    HASHKEY CLASS TEXTHASHKEY(T); VALUE T; TEXT T;
    BEGIN
        INTEGER PROCEDURE HASH;
        BEGIN
            INTEGER I;
            T.SETPOS(1);
            WHILE T.MORE DO
                I := 31*I+RANK(T.GETCHAR);
            IF DEBUG THEN BEGIN
                OUTIMAGE;
                OUTTEXT("HASHMAPS.TEXTHASHKEY.HASH=");
                OUTINT(I,0);
                OUTIMAGE;
            END;
            HASH := I;
        END HASH;
        BOOLEAN PROCEDURE EQUALTO(K); REF(HASHKEY) K;
            EQUALTO := T = K QUA TEXTHASHKEY.T;
    END TEXTHASHKEY;

Skew

Works with: skewc version 0.9.19

In Skew, interfaces must be explicitly implemented with `::`.

@entry
def main {
  var rgb = Rgb.new(0, 255, 255)
  var hex = Hex.new("00ffff")

  var color Color
  color = hex
  color.print

  color = rgb
  color.print

  (hex as Color).print
}

interface Color {
  def toString string
  def print {
    dynamic.console.log(self.toString)
  }
}

class Rgb :: Color {
  var r int, g int, b int
  def toString string { return "rgb(\(r), \(g), \(b))" }
}

class Hex :: Color {
  var code string
  def toString string { return "#\(code)" }
}


Smalltalk

A class is declared abtract by responding to the query isAbstract with true, and defining the required protocol for subclasses to raise an error notification. Optionally, instance creation can be blocked (but seldom done, as you will hit a subclassResponsibility anyway soon). Typically, the IDE provides menu functions to generate these definitions automatically (eg. "Insert Abstract Class" in the refactoring submenu of the class browser):

someClass class >> isAbstract
    ^ true

someClass class >> new
    self isAbstract ifTrue:[
        ^ self error:'trying to instantiate an abstract class'
    ].
    ^ super new

someClass >> method1
    ^ self subclassResponsibility

Standard ML

Standard ML supports data abstraction through its module system. Every module has a signature describing the types and values that can be accessed from outside a module.

The act of giving a signature to a module is called ascription. There are two type of ascription: Transparent (written :) and opaque (written :>). If a structure is ascribed transparently, none of the types are abstract. If it is ascribed opaquely, all types are abstract by default, but can be specified explicitly in the signature, in which case they are not abstract.

Here is an example signature for a queue data structure:

signature QUEUE = sig
  type 'a queue
  val empty : 'a queue
  val enqueue : 'a -> 'a queue -> 'a queue
  val dequeue : 'a queue -> ('a * 'a queue) option
end

Because we did not specify an implementation for 'a queue, the type will be abstract if we use opaque ascription. Instead we could create a version of the signature which specifies the type, in which case it will never be abstract:

signature LIST_QUEUE = sig
  type 'a queue = 'a list
  val empty : 'a queue
  val enqueue : 'a -> 'a queue -> 'a queue
  val dequeue : 'a queue -> ('a * 'a queue) option
end

Then say we have a structure ListQueue which implements queues as lists. If we write ListQueue :> QUEUE then the queue type will be abstract, but if we write ListQueue : QUEUE or ListQueue : LIST_QUEUE it won't.

Swift

Swift uses Protocols to provide abstract type features. See the docs

A trivial example showing required properties and methods, and the means of providing a default implementation.

protocol Pet {
	var name: String { get set }
	var favouriteToy: String { get set }

	func feed() -> Bool

	func stroke() -> Void

}

extension Pet {
    // Default implementation must be in an extension, not in the declaration above

    func stroke() {
		print("default purr")
	}
}

struct Dog: Pet {
	var name: String
	var favouriteToy: String
	
	// Required implementation
	func feed() -> Bool {
		print("more please")
		return false
	}
	// If this were not implemented, the default from the extension above
	// would be called.
	func stroke() {
		print("roll over")
	}
}

Tcl

Works with: Tcl version 8.6

or

Library: TclOO

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

oo::class create AbstractQueue {
    method enqueue item {
        error "not implemented"
    }
    method dequeue {} {
        error "not implemented"
    }
    self unexport create new
}


Vala

public abstract class Animal : Object {
  public void eat() {
    print("Chomp! Chomp!\n");
  }
  
  public abstract void talk();
}

public class Mouse : Animal {
  public override void talk() {
    print("Squeak! Squeak!\n");
  }
}

public class Dog : Animal {
  public override void talk() {
    print("Woof! Woof!\n");
  }
}

void main() {
  Dog mike = new Dog();
  Mouse scott = new Mouse();

  mike.talk();
  mike.eat();
  scott.talk();
  scott.eat();
}
Output:
Woof! Woof!
Chomp! Chomp!
Squeak! Squeak!
Chomp! Chomp!

VBA

In VBA a class can implement properties declared by an other class, the interface class. The implementing class states "Implements <name of interface class". The names of the implemented properties are prepended by the name of the interface class and an underscore "_". Names of (interface) classes and properties can therefore not contain an underscore.

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

Interfaces

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

Interface IBase
   Sub Method_Must_Be_Implemented()
End Interface

V (Vlang)

Translation of: Go

V (Vlang) interface type is an abstract type. It defines a set of methods that a concrete type must have to satisfy it.

A variable of an interface type can hold a value of any type that implements the methods that are specified in the interface. You don't need to explicitly "declare" that the type "implements" the interface or anything like that -- the compatibility is purely structural based on the methods.

In the following example, the Dog and Cat types both satisfy the Beast interface because they each have the specified methods. The bprint function can print details for any Beast.

interface Beast {
    kind() string
    name() string
    cry() string
}
 
struct Dog {
    kind string
    name string
}
 
fn (d Dog) kind() string { return d.kind }
 
fn (d Dog) name() string { return d.name }
 
fn (d Dog) cry() string { return "Woof" }
 
struct Cat {
    kind string
    name string
}
 
fn (c Cat) kind() string { return c.kind }
 
fn (c Cat) name() string { return c.name }
 
fn (c Cat) cry() string { return "Meow" }
 
fn bprint(b Beast) {
    println("${b.name()}, who's a ${b.kind()}, cries: ${b.cry()}.")
}
 
fn main() {
    d := Dog{"labrador", "Max"}
    c := Cat{"siamese", "Sammy"}
    bprint(d)
    bprint(c)
}
Output:
Max, who's a labrador, cries: "Woof".
Sammy, who's a siamese, cries: "Meow".

Wren

Wren doesn't support interfaces but one can effectively create an abstract class by giving it methods but no constructor. Concrete classes can then inherit from the abstract class and either override, or simply inherit, its methods appropriately.

The Go example, when rewritten in Wren, looks like this.

import "./fmt" for Fmt

class Beast{
    kind {}
    name {}
    cry() {}
    print() { System.print("%(name), who's a %(kind), cries: %(Fmt.q(cry())).") }
}

class Dog is Beast {
    construct new(kind, name) {
        _kind = kind
        _name = name
    }
    kind { _kind }
    name { _name }
    cry() { "Woof" }
}

class Cat is Beast {
    construct new(kind, name) {
        _kind = kind
        _name = name
    }
    kind { _kind }
    name { _name }
    cry() { "Meow" }
}

var d = Dog.new("labrador", "Max")
var c = Cat.new("siamese", "Sammy")
d.print()
c.print()
Output:
Max, who's a labrador, cries: "Woof".
Sammy, who's a siamese, cries: "Meow".

zkl

In zkl, nothing is ever abstract, objects are always runnable. However, it is easy to define "meta" objects, objects that define an interface/api for a "class" of objects. For example, it is desirable for "stream" objects (such as File, List, etc) to share semantics so that code doesn't need to know what the source object really is.

class Stream{	// Mostly virtural base class
   var [proxy protected]
      isBroken = fcn { _broken.isSet() },
      isClosed = fcn { return(_closed.isSet() or _broken.isSet()); };
   fcn init{
      var [protected]
         _closed	= Atomic.Bool(True),
	 _broken	= Atomic.Bool(False),
	 whyBroken	= Void;
   }
   fcn clear	  { _closed.clear(); _broken.clear(); return(self.topdog); }
   fcn open       { return(topdog.init(vm.pasteArgs())); }
   fcn toStream   { return(self); }
   fcn close      { _closed.set(); return(self.topdog); }
   fcn flush      { return(self.topdog); }
   fcn read       { throw(Exception.TheEnd); }	// destructive or advance
   fcn readln     { throw(Exception.TheEnd); }
   fcn write(x)	  { return(self.topdog); }
   fcn writeln(x) { return(self.topdog); }
   fcn walker	  { return((0).walker(*,wap((self.topdog.read.fpM(""))))); }
}
  • The topdog property is the "youngest" child in the inheritance tree (root if you view the tree upside down), it allows a "parent" (or super) to access or pass control to, the actual instance.
  • If you wish to "force" method implementation, you can have a meta method throw an NotImplementedError. This is run time thing, not compile time.

And now for a "real" object:

class DevNull(Stream){
   var [const] fileName = "DevNull";	// compatibility with File
   fcn init     { Stream.init() }
   fcn write(x) { return(0); }
}
Cookies help us deliver our services. By using our services, you agree to our use of cookies.