Classes: Difference between revisions
m Type System cathegory |
php |
||
Line 645: | Line 645: | ||
=={{header|PHP}}== |
=={{header|PHP}}== |
||
⚫ | |||
public static $classVar; |
|||
public $instanceVar; // can also initialize it here |
|||
function __construct() { |
|||
$instanceVar = 0; |
|||
} |
|||
function someMethod() { |
|||
$instanceVar = 1; |
|||
$classVar = 3; |
|||
} |
|||
} |
|||
$myObj = new MyClass();</php> |
|||
<!-- TODO ;; 2008-01-24 07:35 fill this in when i get a few spare moments |
<!-- TODO ;; 2008-01-24 07:35 fill this in when i get a few spare moments |
||
/* |
/* |
||
Line 799: | Line 812: | ||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
<ruby>class MyClass |
|||
<pre> |
|||
⚫ | |||
@@classVar |
@@classVar |
||
def initialize |
def initialize |
||
Line 810: | Line 822: | ||
end |
end |
||
end |
end |
||
myclass = MyClass.new |
myclass = MyClass.new</ruby> |
||
</pre> |
|||
=={{header|Smalltalk}}== |
=={{header|Smalltalk}}== |
Revision as of 03:30, 29 November 2008
![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.
In object-oriented programming class is a set (a transitive closure) of types bound by the relation of inheritance. It is said that all types derived from some base type T and the type T itself form a class T. The first type T from the class T sometimes is called the root type of the class.
A class of types itself, as a type, has the values and operations of its own. The operations of are usually called methods of the root type. Both operations and values are called polymorphic.
A polymorphic operation (method) selects an implementation depending on the actual specific type of the polymorphic argument. The action of choice the type-specific implementation of a polymorphic operation is called dispatch. Correspondingly, polymorphic operations are often called dispatching or virtual. Operations with multiple arguments and/or the results of the class are called multi-methods. A further generalization of is the operation with arguments and/or results from different classes.
- single-dispatch languages are those that allow only one argument or result to control the dispatch. Usually it is the first parameter, often hidden, so that a prefix notation x.f() is used instead of mathematical f(x).
- multiple-dispatch languages allow many arguments and/or results to control the dispatch.
A polymorphic value has a type tag indicating its specific type from the class and the corresponding specific value of that type. This type is sometimes called the most specific type of a [polymorphic] value. The type tag of the value is used in order to resolve the dispatch. The set of polymorphic values of a class is a transitive closure of the sets of values of all types from that class.
In many OO languages the type of the class of T and T itself are considered equivalent. In some languages they are distinct (like in Ada). When class T and T are equivalent, there is no way to distinguish polymorphic and specific values.
The purpose of this task is to create a basic class with a method, a constructor, an instance variable and how to instantiate it.
Ada
Class is used in many languages to provide both encapsulation, or grouping of data and actions, and type definition. Ada packages provide encapsulation or grouping while type definitions are done using the type reserved word. Types participating in inheritance are named tagged record types.
A package specification has the following form: <ada> package My_Package is
type My_Type is tagged private; procedure Some_Procedure(Item : out My_Type); function Set(Value : in Integer) return My_Type; private type My_Type is tagged record Variable : Integer := -12; end record; end My_Package;</ada>
The type declaration at the top of the package gives public visibility to the private tagged type My_Type. Since My_Type is declared to be private, the public has no visibility of its structure. The type must be treated as a black box. The private section of the package specification includes the actual tagged record definition. Note that the data member Variable is initialized to -12. This corresponds to a default constructor for the type.
The package body must contain the implementation of the procedures and functions declared in the package specification. <ada> package body My_Package is
procedure Some_Procedure(Item : out My_Type) is begin Item := 2 * Item; end Some_Procedure; function Set(Value : Integer) return My_Type is Temp : My_Type; begin Temp.Variable := Value; return Temp; end Set;
end My_Package;</ada> The Set function acts as a conversion constructor for My_Type.
An instance is typically created outside the package: <ada> with My_Package; use My_Package;
procedure Main is Foo : My_Type; -- Foo is created and initialized to -12 begin Some_Procedure(Foo); -- Foo is doubled Foo := Set(2007); -- Foo.Variable is set to 2007 end Main;</ada>
BASIC
DECLARE SUB MyClassDelete (pthis AS MyClass) DECLARE SUB MyClassSomeMethod (pthis AS MyClass) DECLARE SUB MyClassInit (pthis AS MyClass)
TYPE MyClass Variable AS INTEGER END TYPE
DIM obj AS MyClass MyClassInit obj MyClassSomeMethod obj
SUB MyClassInit (pthis AS MyClass) pthis.Variable = 0 END SUB
SUB MyClassSomeMethod (pthis AS MyClass) pthis.Variable = 1 END SUB
ALGOL 68
The following code is experimental. Basically ALGOL 68 is not object oriented, so the task to create (and use of) objects is tedious due to the lack of certain constructs, especially the lack of OO syntactic sugar. For further details:
Other examples of this experimental approach are located at pages: Life in two dimensions, Playing Cards and Stack.
<cpp>MODE MYDATA = STRUCT(
INT name1
); STRUCT(
INT name2, PROC (REF MYDATA)REF MYDATA new, PROC (REF MYDATA)VOID init, PROC (REF MYDATA)VOID some method
) class my data := (
# name2 := # 2, # Class attribute # # PROC new := # (REF MYDATA new)REF MYDATA:( (init OF class my data)(new); new ),
# PROC init := # (REF MYDATA self)VOID:( """ Constructor (Technically an initializer rather than a true 'constructor') """; name1 OF self := 0 # Instance attribute # ), # PROC some method := # (REF MYDATA self)VOID:( """ Method """; name1 OF self := 1; name2 OF class my data := 3 )
);
- class name, invoked as a function is the constructor syntax #
REF MYDATA my data = (new OF class my data)(LOC MYDATA);
MODE GENDEROPT = UNION(STRING, VOID); MODE AGEOPT = UNION(INT, VOID);
MODE MYOTHERDATA = STRUCT(
STRING name, GENDEROPT gender, AGEOPT age
); STRUCT (
INT count, PROC (REF MYOTHERDATA, STRING, GENDEROPT, AGEOPT)REF MYOTHERDATA new, PROC (REF MYOTHERDATA, STRING, GENDEROPT, AGEOPT)VOID init, PROC (REF MYOTHERDATA)VOID del
) class my other data := (
# count := # 0, # Population of "(init OF class my other data)" objects #
# PROC new := # (REF MYOTHERDATA new, STRING name, GENDEROPT gender, AGEOPT age)REF MYOTHERDATA:( (init OF class my other data)(new, name, gender, age); new ),
# PROC init := # (REF MYOTHERDATA self, STRING name, GENDEROPT gender, AGEOPT age)VOID:( """ One initializer required, others are optional (with different defaults) """; count OF class my other data +:= 1; name OF self := name; gender OF self := gender; CASE gender OF self IN (VOID):gender OF self := "Male" ESAC; age OF self := age ),
# PROC del := # (REF MYOTHERDATA self)VOID:( count OF class my other data -:= 1 )
);
PROC attribute error := STRING: error char; # mend the error with the "error char" #
- Allocate the instance from HEAP #
REF MYOTHERDATA person1 = (new OF class my other data)(HEAP MYOTHERDATA, "John", EMPTY, EMPTY); print (((name OF person1), space,
(gender OF person1|(STRING gender):gender|attribute error), new line)); # "John Male" #
print (((age OF person1|(INT age):age|attribute error), new line)); # Raises AttributeError exception! #
- Allocate the instance from LOC (stack) #
REF MYOTHERDATA person2 = (new OF class my other data)(LOC MYOTHERDATA, "Jane", "Female", 23); print (((name OF person2), space,
(gender OF person2|(STRING gender):gender|attribute error), space, (age OF person2|(INT age):age|attribute error), new line)) # "Jane Female 23" #</cpp>
Output:
John Male * Jane Female +23
C
<c>typedef struct MyClass {
int variable;
} MyClass;
struct MyClass* MyClass_new() {
struct MyClass* pthis = (struct MyClass*)malloc( sizeof(struct MyClass) ); //memset(pthis, 0, sizeof(struct MyClass) ); pthis->variable = 0; return pthis;
}
void MyClass_delete(struct MyClass** pthis) {
if(pthis && *pthis) { free(*pthis); *pthis = NULL; }
}
struct void MyClass_someMethod(struct MyClass* pthis) {
pthis->variable = 1;
}
struct MyClass* obj = MyClass_new(); MyClass_someMethod(obj); MyClass_delete(&obj);</c>
C++
<cpp>class MyClass { public:
void someMethod(); // member function = method MyClass(); // constructor
private:
int variable; // member variable = instance variable
};
// implementation of constructor MyClass::MyClass():
variable(0)
{
// here could be more code
}
// implementation of member function void MyClass::someMethod() {
variable = 1; // alternatively: this->variable = 1
}
// Create an instance as variable MyClass instance;
// Create an instance on free store MyClass* pInstance = new MyClass; // Instances allocated with new must be explicitly destroyed when not needed any more: delete pInstance;</cpp>
Note: MyClass instance(); would not define an instance, but declare a function returning an instance. Accidentally declaring functions when object definitions are wanted is a rather common bug in C++.
Functions can also be defined inline:
<cpp>class MyClass { public:
MyClass(): variable(0) {} void someMethod() { variable = 1; }
private:
int variable;
};</cpp>
Note that member functions in C++ by default are not polymorphic; if you want a polymorphic member function, you have to mark it as virtual. In that case, you should also add a virtual destructor, even if that is empty. Example:
<cpp>class MyClass { public:
virtual void someMethod(); // this is polymorphic virtual ~MyClass(); // destructor
};</cpp>
C#
public class MyClass { public MyClass() { } public void SomeMethod() { } private int _variable; public int Variable { get { return _variable; } set { _variable = value; } } public static void Main() { // instantiate it MyClass instance = new MyClass(); // invoke the method instance.SomeMethod(); // set the variable instance.Variable = 99; // get the variable System.Console.WriteLine( "Variable=" + instance.Variable.ToString() ); } }
Common Lisp
(defclass circle () ((radius :initarg :radius :initform 1.0 :type number :reader radius)))
(defmethod area ((shape circle)) (* pi (expt (radius shape) 2)))
> (defvar *c* (make-instance 'circle :radius 2)) > (area *c*) 12.566370614359172d0
D
<d>module Class;
import std.stdio;
class MyClass {
//constructor this() { }
void someMethod() { variable = 1; }
private int _variable;
// getter method int variable() { return _variable; }
// setter method int variable(int new_variable) { return _variable = new_variable; }
}
void main() {
// scope instances are allocated on the heap // this is not really necessary because unneeded objects will be GC'ed scope instance = new MyClass();
// prints 'variable=0' because ints are initialized to 0 by default writefln("variable=", instance.variable); // invoke the method instance.someMethod;
// prints 'variable=1' writefln("variable=", instance.variable);
// set the variable using setter method instance.variable = 99;
// prints 'variable=99' writefln("variable=", instance.variable);
}</d>
E
In E, classes, constructors, and instance variables are not built into the language. This is an example of the basic convention; different cases may call for objects built in different ways.
def makeColor(name :String) { def color { to colorize(thing :String) { return `$name $thing` } } return color }
Example interactive session creating and using it:
? def red := makeColor("red") # value: <color>
? red.colorize("apple") # value: "red apple"
Factor
TUPLE: my-class foo bar baz ; M: my-class quux foo>> 20 + ; C: <my-class> my-class 10 20 30 <my-class> quux ! result: 30 TUPLE: my-child-class < my-class quxx ; C: <my-child-class> my-child-class M: my-child-class foobar 20 >>quux ; 20 20 30 <my-child-class> foobar quux ! result: 30
Forth
ANSI Forth has no object oriented features, but as Forth is a very easy language to extend, many object oriented programming systems have been implemented for it over the years. WinForth has one such system, which is described here.
Declare a class
:class MyClass <super Object int memvar :m ClassInit: ( -- ) ClassInit: super 1 to memvar ;m :m ~: ( -- ) ." Final " show: [ Self ] ;m :m set: ( n -- ) to memvar ;m :m show: ( -- ) ." Memvar = " memvar . ;m ;class
Allocate a static object
MyClass newInstance
Allocate a dynamic object, saving its pointer in a global variable.
New> MyClass value newInstance
Call member functions
10 set: newInstance show: newInstance
Free a dynamically allocated object
newInstance dispose 0 to newInstance \ no dangling pointers!
Example of dynamic allocation and local variable use"
: test { \ obj -- } New> MyClass to obj show: obj 1000 set: obj obj dispose ;
Java
Platform: J2SE <java>public class MyClass {
// instance variable private int variable; // Note: instance variables are usually "private"
/** * The constructor */ public MyClass() { // creates a new instance }
/** * A method */ public void someMethod() { this.variable = 1; // Note: "this." is optional // variable = 1; works also }
}</java>
JavaScript
//constructor function MyClass(initVal) { //instance variable if(initVal == undefined) { this.number = 1; } else { this.number = initVal; } } //method of MyClass MyClass.prototype.getDouble = function() { return this.number * 2; }; var instance1 = new MyClass; //or "new MyClass();" instance1.number = 5; alert( instance1.getDouble() ); //10 var instance2 = new MyClass(3); alert( instance2.getDouble() ); //6
Oberon-2
MODULE M; TYPE T = POINTER TO TDesc; TDesc = RECORD x: INTEGER END; PROCEDURE New*(): T; VAR t: T; BEGIN NEW(t); t.x := 0; RETURN t END New; PROCEDURE (t: T) Increment*; BEGIN INC(t.x) END Increment; END M.
Exported procedures are marked with an asterisk (*). There is nothing special about the constructor New, it is just a function that returns a new object of type T. The name of the method receiver can also be chosen freely. INC is a predeclared procedure that increments its argument.
Object Pascal
- Note: This is not part of standard Pascal, but Turbo Pascal specific
type MyClass = object variable: integer; constructor init; destructor done; procedure someMethod; end; constructor MyClass.init; begin variable := 0; end; procedure MyClass.someMethod; begin variable := 1; end; var instance: MyClass; { as variable } pInstance: ^MyClass; { on free store } begin { create instances } instance.init; new(pInstance, init); { alternatively: pInstance := new(MyClass, init); } { call method } instance.someMethod; pInstance^.someMethod; { get rid of the objects } instance.done; dispose(pInstance, done); end;
Objective-C
Interface:
// There are no class variables, so static variables are used. static int myClassVariable = 0; @interface MyClass : NSObject { int variable; // instance variable } - (int)variable; // Typical accessor - you should use the same name as the variable @end
Implementation:
@implementation MyClass // Was not declared because init is defined in NSObject - init { if (self = [super init]) variable = 0; return self; } - (int)variable { return variable; } @end
Using the class:
// Creating an instance MyClass *mc = [[MyClass alloc] init]; // Sending a message [mc variable]; // Releasing it. When its reference count goes to zero, it will be deallocated [mc release];
OCaml
<ocaml>class my_class =
object (self) val mutable variable = 0 method some_method = variable <- 1 end</ocaml>
Using the class:
# let instance = new my_class;; val instance : my_class = <obj> # instance#some_method;; - : unit = ()
Perl
The implementation (there are no declarations): <perl>{
# a class is a package (i.e. a namespace) with methods in it package MyClass;
# a constructor is a function that returns a blessed reference sub new { my $class = shift; bless {variable => 0}, $class; # the instance object is a hashref in disguise. # (it can be a ref to anything.) };
# an instance method is a function that takes an object as first argument. # the -> invocation syntax takes care of that nicely, see Usage paragraph below. sub someMethod { my $self = shift; $self->{variable} = 1; };
};</perl> Using the class: <perl>my $instance = MyClass->new; # invoke constructor method
$instance->someMethod; # invoke method on object instance
# instance deallocates when the last reference falls out of scope</perl>
PHP
<php>class MyClass {
public static $classVar; public $instanceVar; // can also initialize it here function __construct() { $instanceVar = 0; } function someMethod() { $instanceVar = 1; $classVar = 3; }
} $myObj = new MyClass();</php>
Pop11
Object system is implemented as a library, so we must first load it.
uses objectclass; define :class MyClass; slot value = 1; enddefine;
Defining class MyClass automatically defines two constructors, newMyClass and consMyClass and slot (instance variable) accessors, so we can immediately start using our new class:
;;; Construct instance with default slot values lvars instance1 = newMyClass(); ;;; Construct instance with explicitely given slot values lvars instance2 = consMyClass(15); ;;; Print slot value using dot notation instance1.value => instance2.value => ;;; Print slot value using funtional notation value(instance1) => ;;; Change slot value 12 -> value(instance1); ;;; Print it value(instance1) =>
We can add methods at any time (even after creating an instance):
define :method reset(x : MyClass); 0 -> value(x); enddefine; reset(instance1); ;;; Print it instance1 =>
Python
<python>class MyClass:
name2 = 2 # Class attribute
def __init__(self): """ Constructor (Technically an initializer rather than a true "constructor") """ self.name1 = 0 # Instance attribute def someMethod(self): """ Method """ self.name1 = 1 MyClass.name2 = 3
myclass = MyClass() # class name, invoked as a function is the constructor syntax.
class MyOtherClass:
count = 0 # Population of "MyOtherClass" objects def __init__(self, name, gender="Male", age=None): """ One initializer required, others are optional (with different defaults) """ MyOtherClass.count += 1 self.name = name self.gender = gender if age is not None: self.age = age def __del__(self): MyOtherClass.count -= 1
person1 = MyOtherClass("John") print person1.name, person1.gender # "John Male" print person1.age # Raises AttributeError exception! person2 = MyOtherClass("Jane", "Female", 23) print person2.name, person2.gender, person2.age # "Jane Female 23"</python>
Python allows for very flexible argument passing including normal named parameters, defaulted/optional named parameters, up to one "varargs" tuple, and any number of keywords arguments (which are all passed in the form of a single dictionary (associative array), and any non-ambiguous combination of these). All types of argument passing for functions can also be used for object instantiation/initialization (passed to the special __init__() method) as shown.
New-style classes inherit from "object" or any descendant of the "object" class:
<python>class MyClass(object):
...</python>
These "new-style" classes support some features which were unavailable in "classic classes". New features include a __new__() with lower level control over object instantiation, metaclass support, static methods, class methods, "properties" (managed attributes) and "slots" (attribute restrictions).
RapidQ
TYPE MyClass EXTENDS QObject Variable AS INTEGER CONSTRUCTOR Variable = 0 END CONSTRUCTOR SUB someMethod MyClass.Variable = 1 END SUB END TYPE ' create an instance DIM instance AS MyClass ' invoke the method instance.someMethod
Raven
Build classes:
class Alpha 'I am Alpha.' as greeting define say_hello greeting print
class Beta extend Alpha 'I am Beta!' as greeting
Execute classes to create objects:
Alpha as alpha Beta as beta
Call methods:
alpha.say_hello beta.say_hello
Result:
I am Alpha. I am Beta!
Ruby
class MyClass
@@classVar def initialize @instanceVar = 0 end def someMethod @instanceVar = 1 @@classVar = 3 end
end myclass = MyClass.new
Smalltalk
Object subclass: #MyClass instanceVariableNames: 'instanceVar' classVariableNames: 'classVar' poolDictionaries: '' category: 'Testing' ! !MyClass class methodsFor: 'instance creation'! new ^self basicNew instanceVar := 0 ! ! !MyClass methodsFor: 'testing'! someMethod ^self instanceVar = 1; classVar = 3 ! ! MyClass new someMethod!