Innkapsling (dataprogrammering) - Encapsulation (computer programming)

I objektorientert programmering (OOP) refererer innkapsling til samling av data med metodene som opererer på disse dataene, eller begrensning av direkte tilgang til noen av objektets komponenter. Innkapsling brukes til å skjule verdiene eller tilstanden til et strukturert dataobjekt inne i en klasse , og forhindre direkte tilgang til dem av klienter på en måte som kan avsløre skjulte implementeringsdetaljer eller krenke statlig uoverensstemmelse som metodene opprettholder.

Offentlig tilgjengelige metoder tilbys generelt i klassen for å få tilgang til eller endre staten mer abstrakt. I praksis gis det noen ganger metoder (såkalte "getters" og "setters" ) for å få tilgang til verdiene indirekte, men selv om det ikke nødvendigvis er et brudd på abstrakt innkapsling, blir de ofte betraktet som et tegn på potensielt dårlig objektorientert programmering (OOP) designpraksis (et antimønster ).

Denne mekanismen er ikke unik for OOP. Implementeringer av abstrakte datatyper , f.eks. Moduler , tilbyr en lignende form for innkapsling. Likheten er blitt forklart av programmeringsspråkteoretikere når det gjelder eksistensielle typer .

Betydning

I objektorienterte programmeringsspråk og andre relaterte felt refererer innkapsling til en av to relaterte, men forskjellige forestillinger, og noen ganger til kombinasjonen av disse:

  • En språkmekanisme for å begrense direkte tilgang til noen av objektets komponenter.
  • En språkkonstruksjon som letter samling av data med metodene (eller andre funksjoner) som opererer på disse dataene.

Noen programmeringsspråklige forskere og akademikere bruker den første betydningen alene eller i kombinasjon med den andre som et kjennetegn ved objektorientert programmering , mens noen programmeringsspråk som gir leksikalske avslutninger ser på innkapsling som et trekk i språket ortogonal til objektorientering.

Den andre definisjonen er motivert av det faktum at komponentene i mange objektorienterte språk og andre relaterte felt ikke blir skjult automatisk, og dette kan overstyres; dermed er informasjon som gjemmer seg definert som en egen oppfatning av de som foretrekker den andre definisjonen.

Innkapslingsfunksjonene støttes ved bruk av klasser på de fleste objektorienterte språk, selv om det også finnes andre alternativer.

Innkapsling og arv

Forfatterne av Design Patterns diskuterer spenningen mellom arv og innkapsling i lengden og uttaler at etter deres erfaring, overbrukere designere arv. De hevder at arv ofte bryter innkapslingen, gitt at arv utsetter en underklasse for detaljene i foreldrenes implementering. Som beskrevet av jojo-problemet , kan overforbruk av arv og derfor innkapsling bli for komplisert og vanskelig å feilsøke.

Informasjon gjemmer seg

Under definisjonen av at innkapsling "kan brukes til å skjule datamedlemmer og medlemsfunksjoner", er den interne representasjonen av et objekt generelt skjult utenfor utsikten utenfor objektets definisjon. Vanligvis er det bare objektets egne metoder som kan direkte inspisere eller manipulere feltene. Å skjule det indre av objektet beskytter dets integritet ved å hindre brukere i å sette komponentens interne data til en ugyldig eller inkonsekvent tilstand. En antatt fordel med innkapsling er at det kan redusere systemkompleksiteten og dermed øke robustheten ved å la utvikleren begrense gjensidig avhengighet mellom programvarekomponenter.

Noen språk som Smalltalk og Ruby tillater bare tilgang via objektmetoder, men de fleste andre (f.eks. C ++ , C# , Delphi eller Java ) gir programmereren en grad av kontroll over det som er skjult, vanligvis via søkeord som publicog private. ISO C ++ - standarden refererer til protected, privateog publicsom " tilgangsspesifikatorer ", og at de ikke "skjuler informasjon". Informasjonsskjuling oppnås ved å levere en kompilert versjon av kildekoden som er grensesnitt via en toppfil.

Nesten alltid er det en måte å overstyre slik beskyttelse - vanligvis via refleksjons -API (Ruby, Java, C#, etc.), noen ganger ved mekanisme som navnemangling ( Python ), eller spesiell søkeordbruk som friendi C ++. Systemer som gir kapasitetsbasert sikkerhetobjektnivå (følger objekt-modellen ) er et unntak og garanterer sterk innkapsling.

Eksempler

Begrensning av datafelt

Språk som C ++ , C# , Java , PHP , Swift og Delphi tilbyr måter å begrense tilgangen til datafelt.

Nedenfor er et eksempel i C# som viser hvordan tilgang til et datafelt kan begrenses ved bruk av et privatesøkeord:

class Program
{
    public class Account
    {
        private decimal accountBalance = 500.00m;

        public decimal CheckBalance()
        {
            return this.accountBalance;
        }
    }

    static void Main()
    {
        Account myAccount = new Account();
        decimal myBalance = myAccount.CheckBalance();

        /* This Main method can check the balance via the public
         * "CheckBalance" method provided by the "Account" class 
         * but it cannot manipulate the value of "accountBalance" */
    }
}

Nedenfor er et eksempel i Java :

public class Employee {
    private BigDecimal salary = new BigDecimal(50000.00);
    
    public BigDecimal getSalary() {
        return this.salary;
    }

    public static void main() {
        Employee e = new Employee();
        BigDecimal sal = e.getSalary();
    }
}

Innkapsling er også mulig på ikke-objektorienterte språk. I C , for eksempel, kan en struktur deklareres i den offentlige API -en via overskriftsfilen for et sett med funksjoner som opererer på et dataelement som inneholder datamedlemmer som ikke er tilgjengelige for API -klientene med externsøkeordet.

// Header file "api.h"

struct Entity;          // Opaque structure with hidden members

// API functions that operate on 'Entity' objects
extern struct Entity *  open_entity(int id);
extern int              process_entity(struct Entity *info);
extern void             close_entity(struct Entity *info);
// extern keywords here are redundant, but don't hurt.
// extern defines functions that can be called outside the current file, the default behavior even without the keyword

Klienter ringer API -funksjonene for å tildele, operere og dele objekter av en ugjennomsiktig datatype . Innholdet av denne typen er bare kjent og tilgjengelig for implementering av API -funksjonene; klienter kan ikke få tilgang til innholdet direkte. Kildekoden for disse funksjonene definerer det faktiske innholdet i strukturen:

// Implementation file "api.c"

#include "api.h"

struct Entity {
    int     ent_id;         // ID number
    char    ent_name[20];   // Name
    ... and other members ...
};

// API function implementations
struct Entity * open_entity(int id)
{ ... }

int process_entity(struct Entity *info)
{ ... }

void close_entity(struct Entity *info)
{ ... }

Navn mangling

Nedenfor er et eksempel på Python , som ikke støtter variable tilgangsbegrensninger. Imidlertid er konvensjonen at en variabel hvis navn er prefiks med en understrek, skal betraktes som privat.

class Car: 
    def __init__(self) -> None:
        self._maxspeed = 200
 
    def drive(self) -> None:
        print(f"Maximum speed is {self._maxspeed}.")
 
redcar = Car()
redcar.drive()  # This will print 'Maximum speed is 200.'

redcar._maxspeed = 10
redcar.drive()  # This will print 'Maximum speed is 10.'

Se også

Referanser