Klaso (programifo)

En objekt-orientizita programifo, **klaso** deklaras propraji komuna a ensemblo di objekti. La klaso deklaras atributi reprezentanta la stando dil objekti e dil metodi reprezentanta lia konduto.

Do, klaso reprezentas kategorio di objekti. Lu aparas anke kom "modelo" o "fabrikerio" de qua es posibla krear objekti (lu es un-maniere "instrumentaro" qua permisas fabrikar objekto). On parolas do pri objekto kom instanco (*instance*) di klaso (kreo di objekto havanta la propraji dil klaso).

Es posibla restriktar la ensemblo di objekti reprezentata da klaso A pro mekanismo di heredo. En ica kazo, on kreas nova klaso B ligata al klaso A e qua adjuntas nova propraji. En ica kazo, diversa termini uzesas:

* A es **generaliguro** di B e B es **specaliguro** di A;
* A es **superklaso** di B e B es **subklaso** di A;
* A es la **matrala klaso** di B e B es **filiala klaso** di A.

## Exempli di klaso
En la exempli infre es definata en diversa lingui klaso `Point` kun du atributi `x` e `y`. Ica klaso kontenas un konstrukto-metodo (*constructor*), du metodi retrodonanta la valoro dil atributi (`getX()` e `getY()`), un metodo determinanta se la punto reprezentas l'origino (`isOrigin()`) e un metodo efektiganta translaco. 

### En [[C plus plus|C++]]

```c
class Point 
{
private:
  int x;
  int y;

public:
  Point(int x, int y) : x(x), y(y) {}

  int getX() const { return x; }
  int getY() const { return y; }

  bool isOrigin() const { return x == 0 && y == 0; }

  Point translate(const Point& point) const 
  {
    return Point(x + point.getX(), y + point.getY());
  }
};
```


### En [[C sharp|C#]]

```csharp
class Point
{
	public Point(int x, int y)
	{
		X = x;
		Y = y;
	}

	public int Y { get; private set; }

	public int X { get; private set; }

	public bool IsOrigin()
	{
		return X == 0 && Y == 0;
	}

	public Point Translate(Point p)
	{
		return new Point(X + p.X, Y + p.Y);
	}
}
```


### En [[Java (linguo)|Java]]

```java
public class Point 
{
	private int x;
	private int y;

	public Point(int x, int y)
	{
		this.x = x;
		this.y = y;
	}

	public int getX() 
	{
		return x;
	}
	
	public int getY()
	{	
		return y;
	}

  	public boolean isOrigin()
	{
		return (x == 0) && (y == 0); 
	}

	public Point translate(Point pt)
	{
		return new Point(x + pt.getX(), y + pt.getY());
	}
}
```


### En [[Object Pascal]]

```pascal
unit Point;

interface

type
  TPoint = class
  protected
    fX, fY: integer;
    function GetY : integer;
  public
    property X : integer read fX;   //Kun implicita aceso-metodo
    property Y : integer read GetY; //Sen implicita aceso-metodo
    constructor Create(X, Y: integer); overload;
    constructor Create; overload;
    function IsOrigin: Boolean;
    function Translate(Pt: TPoint): TPoint;
  end;

implementation

function TPoint.GetY: integer;
begin
  Result := fY;
end;

constructor TPoint.Create(X, Y: integer);
begin
  fX := X;
  fY := Y;
end;

constructor TPoint.Create;
begin
  Create(0,0);
end;

function TPoint.IsOrigin: Boolean;
begin
  Result := (fX = 0) and (fY = 0);
end;

function TPoint.Translate(Pt: TPoint): TPoint;
begin
  Result := TPoint.Create(fX + Pt.X, fY + Pt.Y);
end;

end.
```


### En [[PHP]]

```php
class Point {
  private $x;
  private $y;

  public function __construct($x, $y) {
    $this->x = (int) $x;
    $this->y = (int) $y;
  }

  public function getX() { return $this->x; }
  public function getY() { return $this->y; }

  public function isOrigin() { return ($this->x == 0) && ($this->y == 0); }

  public function translate(Point $point) {
    return new Point($this->x + $point->getX(), $this->y + $point->getY());
  }
}
```


### En [[Ruby]]

```ruby
class Point
	attr_reader :x, :y

	def initialize(x, y)
		@x = x.to_i
		@y = y.to_i
	end

	def origin?
		@x.zero? and @y.zero?
	end

	def translate p
		 Point.new(@x + p.x, @y + p.y)
	end
end
```


### En [[Python (linguo)|Python]]

```python
class Point(object):
    def __init__(self, x, y):
        super(Point, self).__init__()
        self._x = x
        self._y = y

    @property
    def x(self):
        return self._x

    @property
    def y(self):
        return self._y

    def is_origin(self):
        return (self._x == 0) and (self._y == 0)

    def __add__(self, point):
        return Point(self._x + point.x, self._y + point.y)
```


### En [[Visual Basic .NET|VB.Net]]

```vbnet
Public class Point
  Protected intX As Integer, intY As Integer

  Public Sub New(ByVal pX As Integer, ByVal pY As Integer)
    Me.intX = pX
    Me.intY = pY
  End Sub

  Public ReadOnly Property X() As Integer
    Get
      Return Me.intX
    End Get
  End Property

  Public ReadOnly Property Y() As Integer
    Get
      Return Me.intY
    End Get
  End Property

  Public Function IsOrigine() As Boolean
    Return ((Me.intX = 0) And (Me.intY = 0))
  End Function

  Public Function Translate(ByVal pP As Point) As Point
    Return New Point(Me.intX + pP.x, Me.intY + pP.y)
  End Function
```


### En [[Ada (linguo)|Ada]], pos Ada95

```ada
package Point_Pack is
   -- klaso en Ada es tipo nomita "etiketizata"
   -- hike on decidas pluse celar la contenajo dil tipo (privata parto)
   type Point is tagged private;

   -- la metodi deklaresas exter la tipo
   function Get_X (P : Point) return Integer;
   function Get_Y (P : Point) return Integer;
   function Is_Origin (P : Point) return Boolean;
   function Translate (P, Vector : Point) return Point;

   -- nula konstrukto-metodo "integrigita"
   function New_Point (X, Y : Integer) return Point;

private
   -- defini neacesebla al uzanto dil tipo
   type Point is tagged record
      X, Y : Integer;
   end record;
end Point_Pack;

-- la serio kontenas la implementaciono dil klaso: en Ada es importanta separar 
-- la kodexo (la korpo) e la deklari "videbla" (la specigo): generale en 2 diversa faili 
package body Point_Pack is
-- la metodi nomas explicite l'objekto en argumento
   function Get_X (P : Point) return Integer is
   begin
      return P.X;
   end Get_X;

   function Get_Y (P : Point) return Integer is
   begin
      return P.Y;
   end Get_Y;

   function Is_Origin (P : Point) return Boolean is
   begin
      return P.X = 0 and then P.Y = 0;
   end Is_Origin;

   function Translate (P, Vector : Point) return Point is
   begin
      return Point'( X => P.X + Vector.X, Y => P.Y + Vector.Y );
   end Translate;

   function New_Point (X, Y : Integer) return Point is
   begin
      return Point'(X => X, Y => Y);
   end New_Point;

end Point_Pack;
```


## Partikulara kazi di klaso
### Nechanjebla klaso
Klaso nomesas nechanjebla se ne es posibla modifikar objekto di ica klaso pos lua kreo. Exemple, la klaso Point, deskriptita supre en diversa lingui, es nechanjebla pro ke lu expozas nula metodo permisanta di modifikar la valoro di lua membro-variebli. La metodo `translate` retrodonas un nova objekto vice modifikar l'objekto ipsa. La klaso `java.lang.String` dil cirkumaji Java es altra exemplo di klaso nechanjebla, e anke la klaso `System.String` dil *framework* Microsoft .NET.

### Abstraktala klaso
En certa lingui, klaso povas esar partale definata. 
Partikulare, certa metodi di ica klaso havas nula korpo o  implementaciono. Ica metodi nomesas "abstraktala" (o virtuala en C++).

La klasi posedanta adminime un abstraktala metodo anke nomizesas abstraktala (o virtuala) klasi e on ne povas krear la exemplo direte ecepte ke kreante ne abstraktala subklaso.

; Exemplo: On deziras modelar la relati objektala di vektorala desegno. On povas dicar ke desegno-objekto es ensemblo di geometrio-figuri (la abstraktala klaso) e singla geometrio-figuro povas esar punto, poligono o lineo ruptita (ica tri klasi heredas de geometrio-figuro). L'abstraktala klaso ne es do nekarebla en lu ipsa, ma lu es nekarebla por apta, generala e simpligita modelo.

### Interkonekto
Klaso posedanta nur abstraktala metodi nomizesas interkonekto (*interface*) o pure virtuala klaso (en C++) o protokolo (en Objective C).

### Metaklaso
La klaso di klaso es metaklaso. La metaklasi permisas realigar la strukturala reflekto.

## Manipulo dil membr-donaji
### Aceso al membri di klaso
Klaso, quale definita antee, es ensemblo di membri kun tipi (metodi ed atributi) quon on necese guidesas a manipular. 
Se `p` es instanco di `Point(a,b)` ube `a` e `b` es di tipo `int`, on acesas al membri di `p` simile ad ico:

* `p.x = a` e `p.y = b` (aceso al atributi) 
* `p.getX()` e `p.getY()` (aceso al metodi) 

La questiono qua venas al mento es la sequanta: pro quo definar metodo `getX()`, se on povas acesar direte al feldi `x` e `y` dil klaso `Point`?

Fakte, kande on guidesas a manipular multa klasi a anke multa relati entre ica klasi (cf. heredo), la skemo, la donaji e la operaci povas divenar tre komplexa 
(specale por individu ne konceptinta la kodexo). 
On havas do rekurso a mekanismo quon on nomizas enkapsulaciono dil donaji, qua direktas celar a certa parti dil programo la feldi dil klaso en sucio di integreso. L'uzanto do goudesas a manipular nur metodi qua aprobesabas :) e qua teorie satisfacas bone lia rolo. 

Segun la principo di enkapsulaciono, la metodi havas **publika** (*public*) aceso - ico signifikas ke ula elemento di programo povas uzar metodo. Pri l'atributi kompozanta la stando, li havas aceso **privata** (*private*) - nur l'objekto ipsa (e do la metodi quin lu kontenas) havas direta aceso a lua atributi. En ica kazo, la sola maniero di acesar a ica atributi es uzar la metodi dil objekto. La atributi ne povas uzesar direte da altra elemento dil programo nek mem altra objekto, mem se ica objekto es dil sama klaso. Altra punto: la omna atributi di objekto qua heredesas es direte acesebla da l'altra membri di ica objekto. 

Relate al lasta dici, esas ofte konfuzeso pri la semantiko dil privata aceso. Le principo di enkapsulaciono implikas  protekto dil atributi quan ni nomizas **vertikala** (nur l'objekto ipsa e la objekti di subklaso havas aceso). Ni trovas ica semantiko en lingui quale Smalltalk, Oz o OCaml. Tamen certa lingui, quale C++, Pascal o Java, pledas por protekto dil atributi quan ni nomizas **horizontala** (la objekti di sama klaso havas aceso, ma la objekti dil subklasi ne havas).

### Kontrolo dil aceso al membri di klaso e videbleso
Certa lingui propozas chanjar la tipo di aceso dil membri di objekto. Ica operaco plenigesas interne dil klasi di ica objekti. Exemple, la C++ e la Pascal propozas la sequanta videblesi:
* **publika**: la membri povas uzesar en/e da irga parto dil programo (la metodi definita icamaniere es videbla e uzebla da la uzanto). 
* **privata** (*private*): la privata membri di klaso es acesebla nur da la objekti di ica klaso, e non da ici di filiala klaso o di altra klaso. 
* **protektata** (*protected*): quale la privata membri, ma li povas uzesar da la filiala klasi.

La semantiko de ica videblesi e lia nombro varias segun la linguo. Exemple, Java propozas defino poke diferante pri la protektata membri (lu extensesas al ensemblo dil objekti dil sama klaso, dil filiala klasi e dil klasi dil sama paketo). Python propozas anke la posibleso di modifikar la videbleso dil membri di klaso, prefixigante la nomo dil membro kun la signo substrekizata ('_'). Exemple, `getX()` es publika metodo, `_getX()` es sole uzebla da la elemento dil sama modulo e `__getX()` es privata.

## Supercharjo di operatoro
Kande on guidesas a manipular donaji di sama tipo (lu es exemplo la kazo di punti en marko), on povas dezirar aplikar operaci ad ica objekti (en senco dil OOP). Tale, la fuzo di du arei (poligoni) donas bone nova areo, quale l'adiciono di du punti donas un nova punto. 
* Por adiciono di punti, unesma metodo esus kreinda un membr-metodo dil klaso Point quan on nominus `translate(Point)` e qua retrodonus nova `Point` subisinta l'adiciono. On havas:

`   
   ...
   p=Point(6,2)
   q=Point(6,3)
   m=Point(0,0)
   m=p.translate(q) // p+q 
   ...
`
* Fakte, plu naturala e multe plu simplacha notizo esus por reprezentar l'adiciono simple per `m = p+q`. Por ico on utilise mekanismo nomizata supercharjo di operatoros, qua ridefinas donita operatoro por donita ago . 

Durez pri nia klaso Point. La sequanta exemplo Python es tre parolanta:
   class Point:
   (...)
     def __add__(self,point):                             # Supercharjo de '+'
       return Point(self.x + point.x, self.y + point.y)
 
   p=Point(0,0)
   q=Point(2,3)
   r=p+q

Tale `r.getX()` retrodonos 2.

## Noti e referi