Comparison of programming languages (object-oriented programming)
Appearance
Object creation and destruction
creation | destruction | |
---|---|---|
C++ (STL) | class variable«(parameters)»; or class *variable = new class«(parameters)»; |
delete pointer; |
C# | class variable = new class(parameters); | variable.Dispose();[1] |
Java | variable.dispose();[1] | |
Objective-C | class *variable = [[class alloc ] init]; or class *variable = [[class alloc ] initWithFoo:parameter «bar:parameter ...»];
|
[variable release]; |
Python | variable = class(parameters) | del variable [1](Normally not needed) |
Visual Basic .NET | Dim variable As New class(parameters) | variable.Dispose()[1] |
Eiffel | Instructions: create variable or create «{TYPE}» variable.make_foo «(parameters)» Expressions: |
[1] |
PHP | $variable = new class(parameters); | unset($variable); |
Perl 5 | «my »$variable = class->new(parameters); | undef($variable); |
Ruby | variable = class.new«(parameters)» | [1] |
Windows PowerShell | $variable = New-Object «-TypeName» class ««-ArgumentList» parameters» | Remove-Variable «-Name» variable |
OCaml | let variable = new class «parameters» or let variable = object members end[2] |
[1] |
F# | let variable = «new »class(«parameters») |
File declaration
class | interface | namespace | |
---|---|---|---|
C++ (STL) | class name« : public parentclasses[3]» { members }; | namespace name { members } | |
C# | class name« : parentclass«, interfaces»» { members } | interface name { members } | |
Java | class name« extends parentclass»« implements interfaces» { members } | package name; members | |
Objective-C | @interface name : parentclass «< protocols >» { instance_fields } method_and_property_declarations @end @implementation name method_implementations @end[4] |
@protocol name members @end | |
Python | class name(parentclasses[3]): Tab ↹ members |
same, declare methods with pass as body | __all__ = [ member1,member2,... ] |
Visual Basic .NET | Class name« Inherits parentclass»« Implements interfaces» members End Class |
Interface name members End Interface |
Namespace name members End Namespace |
Eiffel | class name« inherit parentclasses[3]» members end |
— | |
PHP | class name« extends parentclass»« implements interfaces» { members } | interface name { members } | namespace name; members |
Perl | package name; «@ISA = qw(parentclasses[3]);» members 1; | package name; members | |
Ruby | class name« < parentclass» members end |
||
Windows PowerShell | — | ||
OCaml | class name «parameters» = object «(self)» «inherit parentclass «parameters» «inherit parentclass «parameters» ...[3]»» members end | ||
F# | type name«(parameters)» «as this» = class «inherit parentclass«(parameters)» «as base»» members «interface interface with implementation «interface interface with implementation ...»» end | type name = interface members end | namespace name members |
Class members
Constructors and destructors
constructor | destructor/finalizer | ||
---|---|---|---|
C++ (STL) | class(«parameters») «: initializers[5]» { instructions } | ~class() { instructions } | |
C# | class(«parameters») { instructions } | ~class() { instructions }[6] | |
Java | void finalize() { instructions }[6] | ||
Eiffel | [7] | Implementing {DISPOSABLE}.dispose ensures that dispose will be called when object is garbage collected. | |
Objective-C | - (id)init { instructions... return self; } or - (id)initWithFoo:parameter «bar:parameter ...» { instructions... return self; } |
- (void)dealloc { instructions } | |
Python | def __init__(self«, parameters»): Tab ↹ instructions |
def __del__(self): Tab ↹ instructions | |
Visual Basic .NET | Sub New(«parameters») instructions End Sub |
Overrides Sub Finalize() instructions End Sub | |
PHP | function __construct(«parameters») { instructions } | function __destruct() { instructions } | |
Perl | sub new { my ($class«, parameters») = @_; my $self = {}; instructions ... bless($self, $class); return $self; } | sub DESTROY { my ($self) = @_; instructions } | |
Ruby | def initialize«(parameters)» instructions end |
— | |
Windows PowerShell | — | ||
OCaml | initializer instructions[8] | — | |
F# | do instructions | override this.Finalize() = instructions[6] |
public | private | protected | friend | |
---|---|---|---|---|
C++ (STL) | public: type field; | private: type field; | protected: type field; | [9] |
C# | public type field «= value»; | private type field «= value»; | protected type field «= value»; | internal type field «= value»; |
Java | type field «= value»; | |||
Eiffel | feature field: TYPE |
feature {NONE} field: TYPE |
feature {NONE} field: TYPE |
feature {FRIEND} field: TYPE |
Objective-C | @public type field; | @private type field; | @protected type field; | @package type field; |
Python | self.field = value Just assign a value to it in a method |
self.__field = value Just assign a value to it in a method |
— | |
Visual Basic .NET | Public field As type «= value» | Private field As type «= value» | Protected field As type «= value» | Friend field As type «= value» |
PHP | public $field «= value»; | private $field «= value»; | protected $field «= value»; | |
Perl | $self->{field} = value; Just assign a value to it in a method |
— | ||
Ruby | — | @field = value Just assign a value to it in a method |
||
Windows PowerShell | Add-Member «-MemberType »NoteProperty «-Name »Bar «-Value »value -InputObject variable |
— | ||
OCaml | — | val «mutable» field = value | — | |
F# | — | let «mutable» field = value | — |
Methods
basic/void method | value-returning method | |
---|---|---|
C++ (STL)[10] | void foo(«parameters») { instructions } | type foo(«parameters») { instructions ... return value; } |
C# | ||
Java | ||
Eiffel | foo ( «parameters» ) do instructions end |
foo ( «parameters» ): TYPE do instructions... Result := value end |
Objective-C | - (void)foo«:parameter «bar:parameter ...»» { instructions } | - (type)foo«:parameter «bar:parameter ...»» { instructions... return value; } |
Python | def foo(self«, parameters»): Tab ↹ instructions |
def foo(self«, parameters»): Tab ↹ instructions Tab ↹ return value |
Visual Basic .NET | Sub Foo(«parameters») instructions End Sub |
Function Foo(«parameters») As type instructions ... Return value End Function |
PHP | function foo(«parameters») { instructions } | function foo(«parameters») { instructions ... return value; } |
Perl | sub foo { my ($self«, parameters») = @_; instructions } | sub foo { my ($self«, parameters») = @_; instructions ... return value; } |
Ruby | def foo«(parameters)» instructions end |
def foo«(parameters)» instructions expression resulting in return value end or def foo«(parameters)» instructions return value end |
Windows PowerShell | Add-Member «-MemberType» ScriptMethod «-Name» foo «-Value» { «param(parameters)» instructions } -InputObject variable | Add-Member «-MemberType» ScriptMethod «-Name» foo «-Value» { «param(parameters)» instructions ... return value } -InputObject variable |
OCaml | — | method foo «parameters» = expression |
F# | member this.foo(«parameters») = expression |
How to declare a property named "Bar"
read-write | read-only | write-only | |
---|---|---|---|
C++ (STL) | — | ||
C# | type Bar { get { instructions ... return value; } set { instructions } } |
type Bar { get { instructions ... return value; } } | type Bar { set { instructions } } |
Java | — | ||
Objective-C | @property (readwrite) type bar; and then inside @implementation either @synthesize bar; or - (type)bar { instructions } |
@property (readonly) type bar; and then inside @implementation either @synthesize bar; or - (type)bar { instructions } |
|
Eiffel | feature -- Access x: TYPE assign set_x feature -- Settings set_x (a_x: like x) do instructions ensure x_set: verification end |
||
Python | def setBar(self, value): Tab ↹ instructions def getBar(self): Tab ↹ instructions Tab ↹ return value bar = property(getBar, setBar) |
def getBar(self): Tab ↹ instructions Tab ↹ return value bar = property(getBar) |
def setBar(self, value): Tab ↹ instructions bar = property(fset = setBar) |
Visual Basic .NET | Property Bar As type Get instructions Return value End Get Set (ByVal Value As type) instructions End Set End Property |
ReadOnly Property Bar As type Get instructions Return value End Get End Property |
WriteOnly Property Bar As type Set (ByVal Value As type) instructions End Set End Property |
PHP | function __get($property) { switch ($property) { case 'Bar' : instructions ... return value; } } function __set($property, $value) { switch ($property) { case 'Bar' : instructions } } |
function __get($property) { switch ($property) { case 'Bar' : instructions ... return value; } } |
function __set($property, $value) { switch ($property) { case 'Bar' : instructions } } |
Perl | — | ||
Ruby | def bar instructions expression resulting in return value end def bar=(value) instructions end or attr_accessor :bar |
def bar instructions expression resulting in return value end or attr_reader :bar |
def bar=(value) instructions end or attr_writer :bar |
Windows PowerShell | Add-Member «-MemberType »ScriptProperty «-Name »Bar «-Value »{ instructions ... return value } «-SecondValue »{ instructions } -InputObject variable |
Add-Member «-MemberType »ScriptProperty «-Name »Bar «-Value »{ instructions ... return value} -InputObject variable |
Add-Member «-MemberType »ScriptProperty «-Name »Bar -SecondValue { instructions } -InputObject variable |
OCaml | — | ||
F# | member this.Bar with get() = expression and set(value) = expression | member this.Bar = expression | member this.Bar with set(value) = expression |
unary | binary | index | type cast | |
---|---|---|---|---|
C++ (STL) | type operatorsymbol() { instructions } | type operatorsymbol(type operand2) { instructions } | type operator[](type index) { instructions } | operator returntype() { instructions } |
C# | static type operator symbol(type operand) { instructions } | static type operator symbol(type operand1, type operand2) { instructions } | type this[type index] { get{ instructions } set{ instructions } } |
static explicit operator returntype(type operand) { instructions } |
Java | — | |||
Objective-C | ||||
Eiffel [11] | op_name alias "symbol": TYPE do instructions end |
op_name alias "symbol" (operand: TYPE1): TYPE2 do instructions end |
bracket_name alias "[]" (index: INTEGER; ...) TYPE do instructions end |
— |
Python | def __opname__(self): Tab ↹ instructions Tab ↹ return value |
def __opname__(self, operand2): Tab ↹ instructions Tab ↹ return value |
def __getitem__(self, index): Tab ↹ instructions Tab ↹ return value def __setitem__(self, index, value): Tab ↹ instructions |
— |
Visual Basic .NET | Shared Operator symbol(operand As type) As type instructions End Operator |
Shared Operator symbol(operand1 As type, operand2 As type) As type instructions End Operator |
Default Property Item(Index As type) As type Get instructions End Get Set(ByVal Value As type) instructions End Set End Propery |
Shared casttype[12] Operator CType(operand As type) As returntype instructions End Operator |
PHP | [13] | [14] | — | |
Perl | use overload "symbol" => sub { my ($self) = @_; instructions }; | use overload "symbol" => sub { my ($self, $operand2, $operands_reversed) = @_; instructions }; | — | |
Ruby | def symbol instructions expression resulting in return value end |
def symbol(operand2) instructions expression resulting in return value end |
def [](index) instructions expression resulting in return value end def []=(index, value) instructions end |
— |
Windows PowerShell | — | |||
OCaml | ||||
F# | static member (symbol) operand = expression | static member (symbol) (operand1, operand2) = expression | member this.Item with get(index) = expression and set index value = expression |
Member access
How to access members of an object x
object member | class member | namespace member | |||
---|---|---|---|---|---|
method | field | property | |||
C++ (STL) | x.method(parameters) or ptr->method(parameters) |
x.field or ptr->field |
cls::member | ns::member | |
Objective-C | [x method«:parameter «bar:parameter ...»»] | x->field | x.property (2.0 only) or [x property] |
[cls method«:parameter «bar:parameter ...»»] | |
C# | x.method(parameters) | x.field | x.property | cls.member | ns.member |
Java | — | ||||
Python | x.property | ||||
Visual Basic .NET | |||||
Windows PowerShell | [cls]::member | ||||
F# | — | cls.member | |||
Eiffel | x.method«(parameters)» | x.field | {cls}.member | — | |
Ruby | — | x.property | cls.member | ||
PHP | x->method(parameters) | x->field | x->property | cls::member | ns\member |
Perl | x->method«(parameters)» | x->{field} | cls->method«(parameters)» | ns::member | |
OCaml | x#method «parameters» | — |
Member availability
Has member? | Handler for missing member | |||
---|---|---|---|---|
Method | Field | Method | Field | |
C++ (STL) | — | |||
Objective-C | [x respondsToSelector:@selector(method)] | — | forwardInvocation: | — |
C# | — | |||
Java | ||||
Eiffel | ||||
Python | hasattr(x, "method") and callable(x.method) | hasattr(x, "field") | __getattr__() | |
Visual Basic .NET | ||||
Windows PowerShell | ||||
F# | — | |||
Eiffel | ||||
Ruby | x.respond_to?(:method) | — | method_missing() | — |
PHP | method_exists(x, "method") | property_exists(x, "field") | __call() | __get() / __set() |
Perl | x->can("method") | defined x->{field} | AUTOLOAD | |
OCaml | — |
Special variables
current object | current object's parent object | null reference | |
---|---|---|---|
C++ (STL) | *this | [15] | NULL |
C# | this | base[16] | null |
Java | super[16] | ||
Objective-C | self | super | nil |
Python | self[17] | super(current_class_name, self)[3] super() (3.x only) |
None |
Visual Basic .NET | Me | MyBase | Nothing |
Eiffel | Current | Precursor «{superclass}» «(args)»[16][18] | Void |
PHP | $this | parent[16] | NULL |
Perl | $self[17] | $self->SUPER[16] | undef |
Ruby | self | super«(args)»[19] | nil |
Windows PowerShell | $this | $NULL | |
OCaml | self[20] | super[21] | —[22] |
F# | this | base[16] | null |
Special methods
String representation | Object copy | Value equality | Object comparison | Hash code | Object ID | |
---|---|---|---|---|---|---|
C++ (STL) | x == y[23] | |||||
C# | x.ToString() | x.Clone() | x.Equals(y) | x.CompareTo(y) | x.GetHashCode() | |
Java | x.toString() | x.clone()[24] | x.equals(y) | x.compareTo(y) | x.hashCode() | System.identityHashCode(x) |
Objective-C | [x description] | [x copy][25] | [x isEqual:y] | [x compare:y] | [x hash] | |
Python | str(x)[26] | copy.copy(x)[27] | x == y[28] | cmp(x ,y)[29] | hash(x)[30] | id(x) |
Visual Basic .NET | x.ToString() | x.Clone() | x.Equals(y) | x.CompareTo(y) | x.GetHashCode() | |
Eiffel | x.out | x.twin | x.is_equal(y) | When x is COMPARABLE, one can simply do x < y | When x is HASHABLE, one can simply do x.hash_code | When x is IDENTIFIED, one can simply do x.object_id |
PHP | sprintf("%s", x)[31] | clone x[32] | x == y | spl_object_hash(x) | ||
Perl | "$x"[33] | |||||
Ruby | x.to_s | x.dup or x.clone |
x == y or x.eql?(y) |
x <=> y | x.hash | x.object_id |
Windows PowerShell | x.ToString() | x.Clone() | x.Equals(y) | x.CompareTo(y) | x.GetHashCode() | |
OCaml | Oo.copy x | x = y | Hashtbl.hash x | Oo.id x | ||
F# | x.ToString() | x.Clone() | x.Equals(y) | x.CompareTo(y) | x.GetHashCode() |
Type manipulation
Get object type | Is instance of (includes subtypes) | Upcasting | Downcasting | |
---|---|---|---|---|
C++ (STL) | typeid(x) | dynamic_cast<type *>(&x) != NULL | —[34] | (type) x or dynamic_cast<type*>(ptr) |
C# | x.GetType() | x is type | (type) x | |
Java | x.getClass() | x instanceof class | ||
Objective-C | [x class] | [x isKindOfClass:[class class]] | ||
Visual Basic .NET | x.GetType() | TypeOf x Is type | CType(x, type) | |
Eiffel | x.generating_type | attached {TYPE} x | attached {TYPE} x as down_x | |
Python | type(x) | isinstance(x, type) | —[35] | |
PHP | get_class(x) | x instanceof class | ||
Perl | ref(x) | x->isa("class") | ||
Ruby | x.class or x.type |
x.instance_of?(type) or x.kind_of?(type) | ||
Windows PowerShell | x.GetType() | x -is [type] | —[34] | [type]x |
OCaml | —[36] | (x :> type) | — | |
F# | x.GetType() | x :? type | (x :?> type) |
Contracts
Precondition | Postcondition | Check | Invariant | Loop | |
---|---|---|---|---|---|
C++ (STL) | — | ||||
C# | |||||
Java | |||||
Objective-C | |||||
Visual Basic .NET | |||||
Eiffel | f require tag: expression do end |
f do ensure tag: expression end |
f do check tag: expression end end |
class X invariant tag: expression end |
from invariant tag: expression until expr loop instructions variant tag: expression end |
Python | — | ||||
PHP | |||||
Perl | |||||
Ruby | |||||
Windows PowerShell | |||||
OCaml | |||||
F# |
See also
Notes
- ^ a b c d e f g This language uses garbage collection to release unused memory.
- ^ OCaml objects can be created directly without going through a class.
- ^ a b c d e f This language supports multiple inheritance. A class can have more than one parent class
- ^ Usually the
@interface
portion is placed into a header file, and the@interface
portion is placed into a separate source code file. - ^ An optional comma-separated list of initializers for member objects and parent classes goes here. The syntax for initializing member objects is "member_name(parameters)" This works even for primitive members, in which case one parameter is specified and that value is copied into the member. The syntax for initializing parent classes is "class_name(parameters)". If an initializer is not specified for a member or parent class, then the default constructor is used.
- ^ a b c This is a finalizer rather than a destructor. It is called by the garbage collector when an object is about to be garbage-collected. There is no guarantee on when it will be called or if it will be called at all.
- ^ Any Eiffel procedure can be used as a creation procedure, aka constructors.
- ^ This "initializer" construct is rarely used. Fields in OCaml are usually initialized directly in their declaration. Only when additional imperative operations are needed is "initializer" used. The "parameters to the constructor" in other languages are instead specified as the parameters to the class in OCaml. See the class declaration syntax for more details.
- ^ In C++, you don't declare specific fields to be accessible by outside things. Rather, you declare outside functions and classes to be friends to have access to the class's fields. See friend function and friend class for more details.
- ^ The declaration and implementation of methods in C++ are usually separate. Methods are declared inside the class definition (which is usually included in a header file) using the syntax
- type foo(«parameters»);
- type class::foo(«parameters») { instructions }
- ^ Although Eiffel does not support overloading of operators, it can define operators
- ^ Where casttype is either Widening(may not cause data loss) or Narrowing(data loss possible).
- ^ PHP does not support operator overloading natively, but support can be added using the "operator" PECL package.
- ^ Your class needs to implement the ArrayAccess interface.
- ^ C++ doesn't have a "super" keyword, because multiple inheritance is possible, and so it may be ambiguous which base class is desired. Instead, you can use the
BaseClassName::member
syntax to access an overridden member in the specified base class. Microsoft Visual C++ provides a non-standard keyword "__super" for this purpose; but this is not supported in other compilers.[1] - ^ a b c d e f The keyword here is not a value in itself and it can only be used to access a method of the superclass.
- ^ a b In this language, instance methods are passed the current object as the first parameter, which is conventionally named "self", but this is not required to be the case.
- ^ "Precursor" in Eiffel is actually a call to the method of the same name in the superclass. So Precursor(args) is equivalent to "super.currentMethodName(args)" in Java. There is no way of calling a method of different name in the superclass.
- ^ "super" in Ruby, unlike in other languages, is actually a call to the method of the same name in the superclass. So super(args) in Ruby is equivalent to "super.currentMethodName(args)" in Java. There is no way of calling a method of different name in the superclass.
- ^ In OCaml, an object declaration can optionally start with a parameter which will be associated with the current object. This parameter is conventionally named "self", but this is not required to be the case. It is good practice to put a parameter there so that one can call one's own methods.
- ^ In OCaml, an inheritance declaration ("inherit") can optionally be associated with a value, with the syntax "inherit parent_class «parameters» as super". Here "super" is the name we gave to the variable associated with this parent object. It can be named something else.
- ^ However, if you really wanted the ability to have an "optional" value in OCaml, you would wrap the value inside an
option
type, whose values areNone
andSome x
, which could be used to represent "null reference" and "non-null reference to an object" as in other languages. - ^ assuming that "x" and "y" are the objects (and not a pointer). Can be customized by overloading the object's
==
operator - ^ Only accessible from within the class itself, since the
clone()
method inherited fromObject
is protected, unless the class overrides the method and makes it public. If you use theclone()
inherited fromObject
, your class will need to implement theCloneable
interface to allow cloning. - ^ Implemented by the object's
copyWithZone:
method - ^ Can be customized by the object's
__str__()
method - ^ Can be customized by the object's
__copy__()
method - ^ Can be customized by the object's
__eq__()
method - ^ Can be customized by the object's
__cmp__()
method - ^ Can be customized by the object's
__hash__()
method - ^ Can be customized by the object's
__toString()
method - ^ Can be customized by the object's
__clone()
method - ^ Can be customized by overloading the object's string-convertion operator
- ^ a b Upcasting is implicit in this language. A subtype instance can be used where a supertype is needed.
- ^ Casting between types is not necessary.
- ^ This language doesn't give run-time type information. It is unnecessary because it is statically typed and downcasting is not possible.