1. Objekt och klasser

Idag får du lära dig lite om hur ett typiskt Java-program fungerar. Här är de stora nyheterna: varje Java-program består av klasser och objekt.

Du vet redan vad klasser är, men vad är objekt?

Jag börjar med en analogi. Föreställ dig att du vill göra ett litet skepp. Först måste du skapa en ritning och sedan ge den till fabriken, där ett fartyg kommer att byggas enligt ritningen. Eller kanske dussin. Eller så många fartyg du vill. Dussintals identiska fartyg byggs enligt en enda ritning. Det är det viktiga här.

Det är samma sak i Java-programmering.

Ritningar

En programmerare är som en designer. En designer skapar ritningar och en Java-programmerare skriver klasser. Delar skapas baserat på ritningarna och objekt skapas baserat på klasser.

Först skriver vi klasser (gör ritningar), och sedan, när programmet körs, skapar Java-maskinen objekt baserat på dessa klasser. På samma sätt som fartyg skapas från ritningar.

Det finns bara en ritning, men det kan finnas många fartyg. Fartygen är distinkta - de har olika namn och bär olika laster. Men de är väldigt lika: de delar alla samma design och kan utföra liknande uppgifter.

Eller här är en annan analogi...

Myrstack

En myrstack är ett bra exempel på hur föremål interagerar. Det finns tre klasser av myror i en enkel myrstack: drottningen, soldater och arbetare.

Antalet myror i varje klass är olika. Det finns en enda drottning för hela myrstacken, men det finns dussintals soldater och hundratals arbetarmyror. Tre klasser och hundratals föremål. Myror interagerar med varandra - med myror i samma klass och med myror av andra klasser - enligt stela regler.

Detta är det perfekta exemplet. Allt är exakt så här i ett typiskt program. Det finns ett primärt objekt som skapar objekt av alla andra klasser. Objekten börjar interagera med varandra och med programmets "omvärld". Objektens beteende är internt hårdkodat.

Dessa två analogier är två sidor av samma mynt. Sanningen finns i mitten. Det första exemplet (om en ritning och fartyg) visar förhållandet mellan en klass och objekt i den klassen. Detta är en stark analogi. Det andra exemplet (om en myrstack) visar förhållandet mellan de skrivna klasserna och de objekt som finns när programmet körs.

Du måste först skriva klasser för varje objekt som kommer att finnas i programmet, och sedan även beskriva hur de interagerar. Ja, det stämmer, men det är lättare än det låter.

I Java är alla entiteter objekt vid körning, och att skriva ett program handlar om att beskriva de olika sätten som objekt interagerar. Objekt anropar helt enkelt varandras metoder och skickar de nödvändiga data till dem.

Dokumentation

Och hur vet du vilken data som ska skickas till metoder? Människorna som kom före dig tänkte på allt.

Varje klass har vanligtvis en beskrivning som säger vad den skapades för. Dessutom har varje offentlig metod vanligtvis en beskrivning som anger vad den gör och vilken data som behöver skickas till den.

För att använda en klass måste du ha en allmän uppfattning om vad den gör. Och du måste veta exakt vad varje metod gör. Men du behöver inte alls veta hur den gör det. Det är som ett trollspö.

Låt oss ta en titt på koden för att kopiera en fil:

Kopiera filen c:\\data.txt till filen c:\\result.txt
package com.codegym.lesson2;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileCopy
{
   public static void main(String[] args) throws IOException
   {
      FileInputStream fileInputStream = new FileInputStream("c:\\data.txt");
      FileOutputStream fileOutputStream = new FileOutputStream("c:\\result.txt");

      while (fileInputStream.available() > 0)
      {
         int data = fileInputStream.read();
         fileOutputStream.write(data);
      }

      fileInputStream.close();
      fileOutputStream.close();
   }
}

Om du läser den här koden rad för rad kan du gissa vad den gör i allmänna termer. Även om det kräver erfarenhet och övning. Efter ett tag kommer den här koden att verka bekant och förståelig för dig.


2. Designa ett program

Programdesign är en hel konst. Det är enkelt och svårt på samma gång. Enkelt, eftersom det inte finns några strikta lagar: allt som inte är förbjudet är tillåtet. Jo, och det är också det som gör det svårt: det finns många sätt att göra något på och det är inte lätt att hitta det bästa.

Att designa ett program är som att skriva en bok. Å ena sidan skriver du bara bokstäver, ord och meningar. Å andra sidan är handlingen, karaktärerna, interna motsättningar, konflikter, berättarstil, intriger etc. viktiga.

Huvudsaken är att förstå vem du skriver koden till. Och du skriver kod för andra programmerare .

Produktutveckling innebär oundvikligen att göra ändringar: något läggs till här, något annat tas bort där, något omdesignas. Det är så stora, enorma och gigantiska projekt föds ur små iterationer.

Det som är viktigast för koden är att den måste vara begriplig för andra programmerare. Felaktig kod som är förståelig kan korrigeras. Korrekt men obegriplig kod kan inte förbättras.  Allt du kan göra är att kassera det.

Så hur skriver man bra, ren kod?

För att göra detta krävs tre saker:

  • Att skriva bra och begriplig kod i metoder - detta är det enklaste kravet
  • Besluta vilka enheter som ska ingå i programmet
  • Dela upp programmet i logiska delar korrekt

Vad ligger bakom dessa koncept?

Att skriva bra kod i metoder

Om du ens har grundläggande engelska kunskaper, kanske du har märkt hur lätt det kan vara att läsa kod som engelska meningar ibland:

  • class Cat extends Pet— Det betyder att Cat-klassen utökar Pet-klassen
  • while(stream.ready())- så länge streamen är klar...
  • if (a<b) return a; else return b— om aär mindre än b, sedan returnera a, annars returnera b.

Detta är medvetet. Java är ett av flera språk som gör det enkelt att skriva självdokumenterande kod, alltså kod som är begriplig utan kommentarer. I bra Java-kod läser många metoder precis som engelska meningar.

När du skriver kod är din uppgift att göra det så enkelt och kortfattat som möjligt. Tänk bara på om din kod är lätt att läsa så börjar du gå i rätt riktning.

I Java är det vanligt att skriva kod som är lätt att läsa. Helst får all kod för en metod plats på en enda skärm (dvs. 20-30 rader). Detta är normen för hela Java-gemenskapen. Om koden kan förbättras bör den förbättras.

Det bästa sättet att lära sig hur man skriver bra kod är genom övning. Skriv mycket kod, studera andras kod och be mer erfarna kollegor att granska din kod.

Och kom ihåg att i samma ögonblick som du säger till dig själv att "låt vara ifred", upphör din tillväxt.

Besluta vilka enheter som ska ingå i programmet

Du måste skriva kod som andra programmerare kan förstå. Om 9 av 10 programmerare skulle inkludera klasserna A, B och C i ett programs design, bör du också göra klasserna A, B och C i ditt program. Du måste skriva kod som andra kan förstå.

Bra, fungerande, snabb, men icke-standardkod är dålig kod.

Du måste studera andras projekt: det här är det bästa, snabbaste och enklaste sättet att ta till sig all visdom som har samlats i IT-branschen i decennier.

Och förresten, du har redan tillgång till ett utmärkt, populärt och väldokumenterat projekt - Java SDK . Börja med det.

Analysera klasserna och hur de är organiserade. Fundera på varför vissa metoder är statiska och andra inte. Varför har metoderna de specifika parametrarna de har men inte andra. Varför dessa metoder exakt, och varför heter klasserna vad de heter, och varför finns de i deras specifika paket.

När du börjar förstå svaren på alla dessa frågor kommer du att kunna skriva kod som andra kan förstå.

Som sagt, jag vill varna dig för att analysera koden i metoderna för Java SDK. Många av metoderna skrevs om för att maximera hastigheten och deras läsbarhet är tveksam.

Dela upp programmet i logiska delar korrekt

Nästan varje program är uppdelat i delar eller moduler. Varje del ansvarar för sin egen del av programmet.

En dator har ett moderkort, en bildskärm och tangentbord - dessa är alla separata, löst kopplade delar. Dessutom interagerar de på standardiserade sätt: USB, HDMI, etc. Om du spiller kaffe på tangentbordet kan du helt enkelt tvätta bort det i diskhon, låta det torka och sedan fortsätta använda det.

Men en bärbar dator är ett exempel på en monolitisk arkitektur: det verkar som om vi kan urskilja separata logiska delar, men de är mycket mer integrerade. På en MacBookPro måste du ta isär hälften av den bärbara datorn för att rengöra tangentbordet. Och att spilla kaffet på en bärbar dator är en anledning att beställa en ny bärbar dator. Inte en ny kopp kaffe.


3. Skapa dina egna klasser

Men eftersom du bara lär dig programmera bör du börja i det små genom att lära dig skapa dina egna klasser.

Naturligtvis har du redan skapat klasser, men du måste lära dig att förstå vilka klasser som ska ingå i ett program, hur de ska heta och vilka metoder de ska ha. Och hur de ska interagera med varandra.

Lista över enheter

Om du inte vet var du ska börja, börja från början.

När du först börjar designa ett program kan du helt enkelt ta ett papper och skriva ner en lista över de enheter (objekt) som ska finnas i programmet. Och skriv sedan kod enligt principen att varje entitet är en separat klass.

Exempel

Låt oss säga att du vill skriva ett schackspel. Du behöver följande enheter: ett schackbräde och 6 typer av schackpjäser. Bitarna rör sig på olika sätt och har olika värden. Det är logiskt att de är separata klasser. Faktum är att när du först kommer igång, ju fler klasser, desto bättre.

Det är väldigt sällan man träffar en nybörjare som skriver tio klasser istället för två. Istället för att skriva tio klasser älskar nybörjare att skriva två eller kanske bara en. Så skriv gärna fler klasser, mina medprogrammerare. Och din kod kommer att bli tydligare för alla utom kanske dig 😛

Schack

Anta att vi bestämmer oss för att skriva klasser för schack: hur skulle dessa klasser se ut?

Är schackbrädet bara en 8 x 8 array? Det är bättre att skapa en separat klass som internt lagrar en referens till en array. Sedan kan du lägga till massor av användbara metoder i klassen "schackbräde", till exempel för att kontrollera om en specifik cell är tom eller upptagen

I allmänhet, när du kommer igång, vägleds alltid av denna princip: Ett program har olika enheter och en enhet har en typ. Denna typ är klassen.


4. Statiska variabler och metoder

Glöm inte heller att använda statiska variabler och metoder. Om du har en schackpjäs som interagerar med en annan på schackbrädet, behöver din kod en metod som tar referenser till den första och andra pjäsen samt schackbrädet.

Statiska variabler, som kan nås från var som helst i programmet, används vanligtvis för att undvika att ständigt skicka runt referenser till objekt som "alltid existerar".

Till exempel, så här:

Koda Notera
public class ChessBoard
{
   public static ChessBoard board = new ChessBoard();
   public ChessItem[][] cells = new ChessItem[8][8];
   ...
}

public class Game
{
   public static void main(String[] args)
   {
      var board = ChessBoard.board;
      board.cells[0][3] = new King(Color.WHITE);
      board.cells[0][4] = new Queen(Color.WHITE);
      ...
   }
}


En referens till ett enda ChessBoardobjekt.
En 8x8 tvådimensionell matris, inte en statisk variabel.








Lägg bitarna på brädan.

Eller istället för en statisk variabel kan du skapa en metod som returnerar ett singleton-objekt. Till exempel, så här:

public class ChessBoard
{
   private static ChessBoard board = new ChessBoard();
   public static ChessBoard getBoard()
   {
      return board;
   }

   public ChessItem[][] cells = new ChessItem[8][8];
   ...
}

public class Game
{
   public static void main(String[] args)
   {
      var board = ChessBoard.getBoard();
      board.cells[0][3] = new King(Color.WHITE);
      board.cells[0][4] = new Queen(Color.WHITE);
      ...
   }
}