Abstract type
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
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.
ABAP
Abstract Class
<lang ABAP>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.</lang>
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. <lang ABAP>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.</lang>
ActionScript
While ActionScript does not support explicit abstract classes, it does have interfaces. Interfaces in ActionScript may not implement any methods and all methods are public and implicitly abstract. Interfaces can extend other interfaces, and interfaces may be multiply inherited. <lang actionscript>package {
public interface IInterface { function method1():void; function method2(arg1:Array, arg2:Boolean):uint; }
}</lang>
Ada
Interface
Interfaces in Ada may have no components or implemented operation except for ones implemented as null operations. Interfaces can be multiply inherited. <lang ada>type Queue is limited interface; procedure Enqueue (Lounge : in out Queue; Item : in out Element) is abstract; procedure Dequeue (Lounge : in out Queue; Item : in out Element) is abstract;</lang> Interfaces can be declared synchronized or task when intended implementations are to be provided by protected objects or tasks. For example: <lang ada>type Scheduler is task interface; procedure Plan (Manager : in out Scheduler; Activity : in out Job) is abstract;</lang>
Abstract type
Abstract types may provide components and implementation of their operations. Abstract types are singly inherited. <lang ada>with Ada.Finalization; ... type Node is abstract new Ada.Finalization.Limited_Controlled and Queue with record
Previous : not null access Node'Class := Node'Unchecked_Access; Next : not null access Node'Class := Node'Unchecked_Access;
end record; overriding procedure Finalize (X : in out Node); -- Removes the node from its list if any overriding procedure Dequeue (Lounge : in out Node; Item : in out Element); overriding procedure Enqueue (Lounge : in out Node; Item : in out Element); procedure Process (X : in out Node) is abstract; -- To be implemented</lang> Here Node is an abstract type that is inherited from Limited_Controlled and implements a node of a doubly linked list. It also implements the interface of a queue described above, because any node can be considered a head of the queue of linked elements. For the operation Finalize an implementation is provided to ensure that the element of a list is removed from there upon its finalization. The operation itself is inherited from the parent type Limited_Controlled and then overridden. The operations Dequeue and Enqueue of the Queue interface are also implemented.
Agda
Using records for storing the interface methods and instance arguments (which are similar to Haskell type classes) for overloading:
<lang agda>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!" -- </lang>
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.
<lang aikido>class Abs {
public function method1... public function method2...
}</lang> Interfaces in Aikido define a set of functions, operators, classes, interfaces, monitors or threads (but no variables) that must be implemented by a class implementing the interface. <lang aikido>interface Inter {
function isFatal : integer function operate (para : integer = 0) operator -> (stream, isout)
}</lang>
Argile
<lang Argile>use std
(: abstract class :)
class Abs
text name AbsIface iface
class AbsIface
function(Abs)(int)->int method
let Abs_Iface = Cdata AbsIface@ {.method = nil}
.: new Abs :. -> Abs {let a = new(Abs); a.iface = Abs_Iface; a}
=: <Abs self>.method <int i> := -> int
(self.iface.method is nil) ? 0 , (call self.iface.method with self i)
(: implementation :)
class Sub <- Abs { int value }
let Sub_Iface = Cdata AbsIface@ {.method = (code of (nil the Sub).method 0)}
.: new Sub (<int value = -1>) :. -> Sub
let s = new (Sub) s.iface = Sub_Iface s.value = value s
.: .method <int i> :. -> int {this.value + i}
(: example use :)
.:foobar<Abs a>:. {print a.method 12 ; del a} foobar (new Sub 34) (: prints 46 :) foobar (new Sub) (: prints 11 :) foobar (new Abs) (: prints 0 :)</lang>
AutoHotkey
<lang AutoHotkey>color(r, g, b){
static color If !color color := Object("base", Object("R", r, "G", g, "B", b ,"GetRGB", "Color_GetRGB")) return Object("base", Color)
} Color_GetRGB(clr) {
return "not implemented"
}
waterColor(r, g, b){
static waterColor If !waterColor waterColor := Object("base", color(r, g, b),"GetRGB", "WaterColor_GetRGB") return Object("base", WaterColor)
}
WaterColor_GetRGB(clr){ return clr.R << 16 | clr.G << 8 | clr.B }
test: blue := color(0, 0, 255) msgbox % blue.GetRGB() ; displays "not implemented" blue := waterColor(0, 0, 255) msgbox % blue.GetRGB() ; displays 255 return </lang>
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: <lang bbcbasic> 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)</lang>
C
Doing abstract types in C is not particularly trivial as C doesn't really support classes. The following series will show an abstract type, followed by a realizable class that provides the abstract interface, and finally followed by an example of usage.
The header file for the abstract class, interfaceAbs.h <lang c>#ifndef INTERFACE_ABS
- 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</lang>
That will define the abstract class. The next section declares a public interface for a class providing the interface of the abstract class. This class is Silly and the code is in file silly.h. Note the actual structure of the class is not provided here. We don't want it visible. <lang c>#ifndef SILLY_H
- define SILLY_H
- include intefaceAbs.h
typedef struct sillyStruct *Silly; extern Silly NewSilly( double, const char *); extern AbsCls Silly_Instance(void *);
- endif</lang>
Ok. Now it is necessary to provide the implementation of the realizable class. This code should be in silly.c. <lang c>#include "silly.h"
- include <string.h>
- include <stdlib.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)</lang> That last macro, ABSTRACT_METHODS may need a little explanation. First note that macros do a string substitution of the parameter values into the arguments of the defined macro, with a little hitch. In the macro definition the ' ## ' expression is special. Here cName ## _Iface gets converted to Silly_Iface, as 'Silly' replaces cName. So the macro call declares an instance of the class record, and defines a constructor named Silly_Instance, which takes a Silly structure as an arguments and uses the class record it previously set up as well.
The methods MyMethod1, MyMethod2, and MyMethod3 are called through the abstract class interface and do not need to be visible outside this file. Hence, they are declared static.
Now all's left is some example code that uses all this stuff. <lang c>#include <stdio.h>
- include "silly.h"
int main() {
AbsCls abster = Silly_Instance(NewSilly( 10.1, "Green Tomato"));
printf("AbsMethod1: %d\n", Abs_Method1(abster, 5)); printf("AbsMethod2: %s\n", Abs_Method2(abster, 4)); Abs_Method3(abster, 21.55); Abs_Free(abster); return 0;
} </lang>
C#
<lang csharp>abstract class Class1 {
public abstract void method1();
public int method2() { return 0; }
}</lang>
C++
You can declare a virtual function to not have an implementation (called "pure virtual function") by the following "= 0" syntax after the method declaration. A class containing at least one pure virtual function (or inheriting one and not overriding it) cannot be instantiated. <lang cpp>class Abs { public: virtual int method1(double value) = 0; virtual int add(int a, int b){ return a+b; } };</lang> Because C++ allows multiple inheritance of classes, no distinction is made between interfaces and abstract classes.
Clojure
Using defprotocol, we can define what is essentially an interface.
<lang lisp>(defprotocol Foo (foo [this]))</lang>
Common Lisp
In Common Lisp, classes do not implement methods, but methods specialized for particular kinds of arguments may be defined for generic functions. Since we can programmatically determine whether methods are defined for a list of arguments, we can simulate a kind of abstract type. We define an abstract type kons
to which an object belongs if methods for kar
and kdr
are defined for it. We define a type predicate konsp
and a type kons
in terms of the type predicate.
<lang lisp>(defgeneric kar (kons)
(:documentation "Return the kar of a kons."))
(defgeneric kdr (kons)
(:documentation "Return the kdr of a kons."))
(defun konsp (object &aux (args (list object)))
"True if there are applicable methods for kar and kdr on object." (not (or (endp (compute-applicable-methods #'kar args)) (endp (compute-applicable-methods #'kdr args)))))
(deftype kons ()
'(satisfies konsp))</lang>
We can make the built-in types cons
and integer
kons
es. We start with cons
, using the obvious definitions.
<lang lisp>(defmethod kar ((cons cons))
(car cons))
(defmethod kdr ((cons cons))
(cdr cons))
(konsp (cons 1 2)) ; => t (typep (cons 1 2) 'kons) ; => t (kar (cons 1 2)) ; => 1 (kdr (cons 1 2)) ; => 2</lang>
For integers, we'll define the kar
of n to be 1 and the kdr
of n to be n - 1. This means that for an integer n, n = (+ (kar n) (kdr n))
.
<lang lisp>(defmethod kar ((n integer))
1)
(defmethod kdr ((n integer))
(if (zerop n) nil (1- n)))
(konsp 45) ; => t (typep 45 'kons) ; => t (kar 45) ; => 1 (kdr 45) ; => 44</lang>
D
<lang d>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() {}</lang>
Delphi
Abstract Class introduced in Delphi 2006. An abstract class cannot be instantiated and must be derived from in order to be used.
<lang delphi>TSomeClass = class abstract (TObject)
...
end;</lang>
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.
<lang delphi>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;</lang>
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:
<lang e>interface Foo {
to bar(a :int, b :int)
}</lang>
With enforcement, a separate stamp is created which must be applied to the instances. This is analogous to a Java interface.
<lang e>interface Foo guards FooStamp {
to bar(a :int, b :int)
}
def x implements FooStamp {
to bar(a :int, b :int) { return a - b }
}</lang>
Eiffel
<lang 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 </lang>
Fantom
<lang 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 }
} </lang>
F#
A type with only abstract members and without constructors is an interface (when not marked with the AbstractClass
attribute). Example:
<lang fsharp>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</lang>
A type that leaves some or all members unimplemented, is an abstract class. It has to be marked with the AbstractClass
attribute. Example:
<lang fsharp>[<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!"</lang>
Genyris
In Genyris by default there are no constructors. In effect all classes are Abstract until they are used to tag (describe) an object. This in keeping with the language's roots in Description Logic. To prevent the class ever being associated with an instance it suffices to force the validator to fail. <lang genyris>class AbstractStack()
def .valid?(object) nil
tag AbstractStack some-object # always fails</lang>
However this is not much use if we want to use an abstract class to define an interface. Here is a quasi-abstract class which can be used to tag objects if they conform to the class's membership expectations. In this case it wants two methods, .enstack and .destack: <lang genyris>class StackInterface()
def .valid?(object) object and bound? .enstack is-instance? .enstack Closure bound? .destack is-instance? .destack Closure</lang>
So if ever we find an object which conforms to the validator it can be tagged. Here's a 'traditional' class definition using the Object class which does provide a constructor: <lang genyris>class XYZstack(Object)
def .init() var .items () def .enstack(object) setq .items (cons object .items) def .destack() var tmp (car .items) setq .items (cdr .items) tmp</lang>
Now we can tag an object that conforms to the Interface: <lang genyris>tag StackInterface (XYZstack(.new))</lang>
Go
Go's interface type is an abstract type. It defines a set of methods that a value must have. <lang go>interface {
Method1(value float64) int SetName(name string) GetName() string
}</lang>
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.
Groovy
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). <lang groovy>public interface Interface {
int method1(double value) int method2(String name) int add(int a, int b)
}</lang>
An abstract class may implement some of its methods and leave others unimplemented. The unimplemented methods and the class itself must be declared "abstract". <lang groovy>public abstract class Abstract1 {
abstract public int methodA(Date value) abstract protected int methodB(String name) int add(int a, int b) { a + b }
}</lang>
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. <lang groovy>public abstract class Abstract2 implements Interface {
int add(int a, int b) { a + b }
}</lang>
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. <lang groovy>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() }
}</lang>
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: <lang groovy>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"))</lang>
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: <lang haskell>class Eq a where
(==) :: a -> a -> Bool (/=) :: a -> a -> Bool</lang>
Default implementations of the functions can be provided: <lang haskell>class Eq a where
(==) :: a -> a -> Bool (/=) :: a -> a -> Bool x /= y = not (x == y) x == y = not (x /= y)</lang>
Here default implementations of each of the operators is circularly defined in terms of the other, for convenience of the programmer; so the programmer only needs to implement one of them for it to work.
Consider the following function which uses the operator == of the type class Eq from above. The arguments to == above were of the unknown type "a", which is of class Eq, so the type of the expression below now must include this restriction: <lang haskell>func :: (Eq a) => a -> Bool func x = x == x</lang>
Suppose I make a new type <lang haskell>data Foo = Foo {x :: Integer, str :: String}</lang>
One could then provide an implementation ("instance") the type class Eq with this type <lang haskell>instance Eq Foo where
(Foo x1 str1) == (Foo x2 str2) = (x1 == x2) && (str1 == str2)</lang>
And now I can, for example, use the function "func" on two arguments of type Foo.
Icon and Unicon
Unicon does not distinguish between abstract and concrete classes. An abstract class is a class with abstract methods. Icon is not object-oriented.
<lang unicon>class abstraction()
abstract method compare(l,r) # generates runerr(700, "method compare()")
end</lang>
J
J does not support abstract types, as defined here. In J, types are typically treated as a necessary evil, which should be minimized, disguised, hidden, neglected or ignored wherever practical. (2=1+1 regardless of the type of 1 and the type of 2.) And allowing user defined types 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, and the intersections of these domains may or may not be empty.
That said: it's useful to define a type, in the context of J, as "the set of values which may result from a 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.
Java
Methods that don't have an implementation are called abstract methods in Java. A class that contains an abstract method or inherits one but did not override it must be an abstract class; but an abstract class does not need to contain any abstract methods. An abstract class cannot be instantiated. If a method is abstract, it must be public or protected <lang java>public abstract class Abs { abstract public int method1(double value); abstract protected int method2(String name); int add(int a, int b){ return a+b; } }</lang> Interfaces in Java may not implement any methods and all methods are implicitly public and abstract. <lang java>public interface Inter { int method1(double value); int method2(String name); int add(int a, int b); }</lang>
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". <lang logtalk>
- - 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.
</lang>
Lua
Lua does not include built-in object oriented paradigms. These features can be added using simple code such as the following: <lang lua>BaseClass = {}
function class ( baseClass )
local new_class = {} local class_mt = { __index = new_class }
function new_class:new() local newinst = {} setmetatable( newinst, class_mt ) return newinst end
if not baseClass then baseClass = BaseClass end setmetatable( new_class, { __index = baseClass } )
return new_class
end
function abstractClass ( self )
local new_class = {} local class_mt = { __index = new_class }
function new_class:new() error("Abstract classes cannot be instantiated") end
if not baseClass then baseClass = BaseClass end setmetatable( new_class, { __index = baseClass } )
return new_class
end
BaseClass.class = class BaseClass.abstractClass = abstractClass</lang> The 'class' function produces a new class from an existing parent class (BaseClass is default). From this class other classes or instances can be created. If a class is created through the 'abstractClass' function, however, the resulting class will throw an error if one attempts to instantiate it. Example: <lang lua>A = class() -- New class A inherits BaseClass by default AA = A:class() -- New class AA inherits from existing class A B = abstractClass() -- New abstract class B BB = B:class() -- BB is not abstract A:new() -- Okay: New class instance AA:new() -- Okay: New class instance B:new() -- Error: B is abstract BB:new() -- Okay: BB is not abstract</lang>
NetRexx
<lang NetRexx>/* NetRexx */ options replace format comments java crossref savelog 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
</lang>
- 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
<lang 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)</lang>
Sample output:
A box: OOOOO OOOOO OOOOO OOOOO OOOOO A rectangle: RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
Objeck
<lang objeck> class ClassA {
method : virtual : public : MethodA() ~ Int; method : public : MethodA() ~ Int { return 0; }
} </lang>
OCaml
Virtual
The equivalent of what is called abstract type in the other OO examples of this page is just called virtual in Objective Caml to define virtual methods and virtual classes:
<lang ocaml>class virtual foo =
object method virtual bar : int end</lang>
Abstract Type
In OCaml what we call an abstract type is not OO related, it is only a type defined without definition, for example: <lang ocaml>type t</lang> it is used for example to hide an implementation from the interface of a module or for type algebra.
Example of abstracting a type in an interface: <lang ocaml>module Foo : sig
type t
end = struct
type t = int * int
end</lang>
Pure abstract types in the implementation: <lang ocaml>type u type v type 'a t type ut = u t type vt = v t</lang>
ooRexx
Interface
<lang ooRexx>
-- 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"
</lang>
Abstract Type
<lang ooRexx> -- 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</lang>
OxygenBasic
'ABSTRACT TYPE FOR CONTAINING THINGS macro ContainerClass(name,body) type name##Type body class name ' string buffer ' method constructor(sys n=1) buffer=nuls n*sizeof name##Type end method ' method destructor() buffer="" end method ' method GetMembers(sys i,n) as name##Type sys le=len buffer sys en=(n+i)*sizeof name##type if le<en buffer+=nuls en-le 'auto expand end if return i+strptr buffer end method ' end macro 'CREATE CLASS ContainerClass Vector3dArray, {double x,y,z} '... end class 'CREATE OBJECT new Vector3dArray v(100) 'OBTAIN POINTER AND FILL CHUNK let pv=v.GetMembers(50,3) 'offset, quantity pv<=1,2,3, 10,20,30, 100,200,300 '... 'TEST print pv[3].y del v
Oz
There are no abstract types as part of the language, but we can do as in Python and raise exceptions:
<lang oz>declare
class BaseQueue attr contents:nil meth init raise notImplemented(self init) end end
meth enqueue(Item) raise notImplemented(self enqueue) end end
meth dequeue(?Item) raise notImplemented(self dequeue) end end
meth printContents {ForAll @contents Show} end end
Queue = {New BaseQueue init} %% throws</lang>
Pascal and Object Pascal
In ObjectPascal mode FreePascal has classes and abstract methods.
See Delphi
Perl
<lang perl>package AbstractFoo;
use strict;
sub frob { die "abstract" } sub baz { die "abstract" }
sub frob_the_baz {
my $self = shift; $self->frob($self->baz());
}
1;</lang>
Perl 6 inspired roles are provided by the Moose library
<lang perl>package AbstractFoo;
use Moose::Role;
requires qw/frob baz/;
sub frob_the_baz {
my $self = shift; $self->frob($self->baz());
}
1;</lang>
Perl 6
Perl 6 supports roles, which are a bit like interfaces, but unlike interfaces in Java they can also contain some implementation.
<lang perl6> 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
</lang>
PHP
The following is for PHP 5.
Methods that don't have an implementation are called abstract methods in PHP. A class that contains an abstract method or inherits one but did not override it must be an abstract class; but an abstract class does not need to contain any abstract methods. An abstract class cannot be instantiated. If a method is abstract, it must be public or protected <lang php>abstract class Abs { abstract public function method1($value); abstract protected function method2($name); function add($a, $b){ return a + b; } }</lang> Interfaces in PHP may not implement any methods and all methods are public and implicitly abstract. <lang php>interface Inter { public function method1($value); public function method2($name); public function add($a, $b); }</lang>
PicoLisp
<lang PicoLisp># In PicoLisp there is no formal difference between abstract and concrete
- classes, 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 sufficient methods
- defined to survive on its own.
(class +abstractClass)
(dm someMethod> ()
(foo) (bar) )</lang>
Python
<lang python>class BaseQueue(object):
"""Abstract/Virtual Class """ def __init__(self): self.contents = list() raise NotImplementedError def Enqueue(self, item): raise NotImplementedError def Dequeue(self): raise NotImplementedError def Print_Contents(self): for i in self.contents: print i,</lang>
Python allows multiple inheritance and it's more common to implement "mix-in" classes rather than abstract interfaces. (Mix-in classes can implement functionality as well define interfaces).
In this example we're simply following the Python convention of raising the built-in "NotImplementedError" for each function which must be implemented by our subclasses. This is a "purely virtual" class because all of its methods raise the exception. (It is sufficient for __init__ to do so for any partial virtual abstractions since that still ensures that the exception will be raised if anyone attempts to instantiate the base/abstract class directly rather than one of its concrete (fully implemented) descendents).
The method signatures and the instantiation of a "contents" list shown here can be viewed as documentary hints to anyone inheriting from this class. They won't actually do anything in the derived classes (since these methods must be over-ridden therein).
In this case we've implemented one method (Print_Contents). This would be inherited by any derived classes. It could be over-ridden, of course. If it's not over-ridden it establishes a requirement that all derived classes provide some "contents" attribute which must allow for iteration and printing as shown. Without this method the class would be "purely virtual" or "purely abstract." With its inclusion the class becomes "partially implemented."
- Note: This "BaseQueue" example should not be confused with Python's standard library Queue class. That is used as the principle "producer/consumer" communications mechanism among threads (and newer multiprocessing processes).
Starting from Python 2.6, abstract classes can be created using the standard abc module: <lang python>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,</lang>
Racket
<lang scheme>#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)</lang>
REBOL
<lang REBOL>REBOL [ Title: "Abstract Type" Author: oofoe Date: 2009-12-05 URL: http://rosettacode.org/wiki/Abstract_type ]
- The "shape" class is an abstract class -- it defines the "pen"
- property and "line" method, but "size" and "draw" are undefined and
- unimplemented.
shape: make object! [ pen: "X" size: none
line: func [count][loop count [prin self/pen] prin crlf] draw: does [none] ]
- The "box" class inherits from "shape" and provides the missing
- information for drawing boxes.
box: make shape [ size: 10 draw: does [loop self/size [line self/size]] ]
- "rectangle" also inherits from "shape", but handles the
- implementation very differently.
rectangle: make shape [ size: 20x10 draw: does [loop self/size/y [line self/size/x]] ]
- Unlike some languages discussed, REBOL has absolutely no qualms
- about instantiating an "abstract" class -- that's how I created the
- derived classes of "rectangle" and "box", after all.
s: make shape [] s/draw ; Nothing happens.
print "A box:" b: make box [pen: "O" size: 5] b/draw
print [crlf "A rectangle:"] r: make rectangle [size: 32x5] r/draw</lang>
Ruby
The Python and Tcl provisos apply to Ruby too. Nevertheless, a
package called abstraction exists where:
<lang ruby>require 'abstraction'
class AbstractQueue
abstract def enqueue(object) raise NotImplementedError end def dequeue raise NotImplementedError end
end
class ConcreteQueue < AbstractQueue
def enqueue(object) puts "enqueue #{object.inspect}" end
end</lang> So:
irb(main):032:0> a = AbstractQueue.new AbstractClassError: AbstractQueue is an abstract class and cannot be instantiated from /usr/lib/ruby/gems/1.8/gems/abstraction-0.0.3/lib/abstraction.rb:10:in `new' from (irb):32 from :0 irb(main):033:0> c = ConcreteQueue.new => #<ConcreteQueue:0x7fdea114> irb(main):034:0> c.enqueue('foo') enqueue "foo" => nil irb(main):040:0> c.dequeue NotImplementedError: NotImplementedError from (irb):37:in `dequeue' from (irb):40 from :0
Scala
Scala has abstract classes, which are classes that cannot be instantiated. They can contain implementation as well as just interface. Non-abstract classes, on the other hand, cannot contain interfaces without implementation.
Scala also has traits, which may contain implementations or not as needed, without any abstract requirement. On the other hand, traits must be mixed in a class, instead of being directly instantiated. That doesn't matter all that much, as they can be mixed with AnyRef, which is the base parent class of all user-defined classes.
Any element of a trait or class can be made abstract, including types, with a very different meaning that described in this page. Here are some examples:
<lang scala>abstract class X {
type A var B: A val C: A def D(a: A): A
}
trait Y {
val x: X
}</lang>
When integrating with Java, traits without implementation appear as interfaces.
Tcl
or
While in general Tcl does not use abstract classes at all (and has no need at all for interfaces due to supporting multiple inheritance and mixins), an equivalent effect can be had by concealing the construction methods on the class instance; instances are only created by subclassing the class first (or by mixing it in). In this example, the methods are also error-returning stubs... <lang Tcl>oo::class create AbstractQueue {
method enqueue item { error "not implemented" } method dequeue {} { error "not implemented" } self unexport create new
}</lang>
Visual Basic
Abstract Classes
Visual Basic doesn't support abstract classes or implementation inheritance.
Interfaces
In Visual Basic, every class is also an interface that other classes can implement. It has this feature because it is based on COM.
Visual Basic .NET
Abstract Classes
- Overridable means subclasses may change the method's implementation. By default, methods in VB cannot be overridden.
- MustOverride means the subclasses must provide an implementation
- By convention all abstract classes have one or more Protected constructors.
<lang vbnet>MustInherit Class Base
Protected Sub New()
End Sub
Public Sub StandardMethod() 'code End Sub
Public Overridable Sub Method_Can_Be_Replaced() 'code End Sub
Public MustOverride Sub Method_Must_Be_Replaced()
End Class</lang>
Interfaces
Interfaces may contain Functions, Subroutines, Properties, and Events.
<lang vbnet>Interface IBase
Sub Method_Must_Be_Implemented()
End Interface</lang>
- Programming Tasks
- Basic language learning
- Object oriented
- Type System
- ABAP
- ActionScript
- Ada
- Agda
- Aikido
- Argile
- AutoHotkey
- BBC BASIC
- C
- C sharp
- C++
- Clojure
- Common Lisp
- D
- Delphi
- DWScript
- E
- Eiffel
- Fantom
- F Sharp
- Genyris
- Go
- Groovy
- Haskell
- Unicon
- J
- Java
- Logtalk
- Lua
- NetRexx
- NewLISP
- Objeck
- OCaml
- OoRexx
- OxygenBasic
- Oz
- Pascal
- Object Pascal
- Perl
- Perl 6
- PHP
- PicoLisp
- Python
- Racket
- REBOL
- Ruby
- RubyGems
- Scala
- Tcl
- TclOO
- TorqueScript/Omit
- Visual Basic
- Visual Basic .NET
- Applesoft BASIC/Omit
- ALGOL 68/Omit
- AWK/Omit
- BASIC/Omit
- Fortran/Omit
- Factor/Omit
- Falcon/Omit
- Gnuplot/Omit
- Integer BASIC/Omit
- J/Omit
- JavaScript/Omit
- Icon/Omit
- LaTeX/Omit
- Make/Omit
- Mathematica/Omit
- Maxima/Omit
- M4/Omit
- Metafont/Omit
- ML/I/Omit
- Modula-2/Omit
- MOO/Omit
- NSIS/Omit
- Octave/Omit
- PlainTeX/Omit
- PARI/GP/Omit
- Scratch/Omit
- TI-89 BASIC/Omit
- UNIX Shell/Omit
- ZX Spectrum Basic/Omit