CodeGym /Java блог /Случаен /ООП концепции в Java
John Squirrels
Ниво
San Francisco

ООП концепции в Java

Публикувано в групата
Една от най-силните страни на Java е обектно-ориентираното програмиране (ООП). Това е причината, поради която този език стана толкова популярен и е много подходящ за проекти от всяHowъв размер. Какво е обектно-ориентирано програмиране? Това не е магия, но може да изглежда вълшебно, ако наистина се докоснете до него. OOP е за това How да изградите вашия софтуер. Това е концепция or по-скоро набор от oop концепции в Java, които ви позволяват да създавате някои специфични взаимодействия и връзки между Java обекти, за да разработите ефективно и използвате софтуер. ООП концепции в Java - 1Класическото ООП включва 3 + 1 основни концепции. Да започнем с класиката.

Предметът

Java обектите, Howто и обектите от реалния свят, имат две характеристики: състояние и поведение.

Например човешки обект има състояние (име, пол, спи or не...) и поведение (изучава Java, ходи, говори...). Всеки Java обект съхранява състоянието си в полета и излага поведението си чрез методи.

Капсулиране

Капсулирането на данни е скриване на вътрешни данни от външния свят и достъп до тях само чрез публично изложени методи. Какво означава това? Какви данни? Крие се от кого? Скриването означава ограничаване на директния достъп до членовете на данните (полетата) на даден клас.

Как работи в Java:

  1. Полетата са частни
  2. Всяко поле в класа получава два специални метода: getter и setter. Getter методите връщат стойността на полето. Методите на Setter ви позволяват да промените стойността на полето по индиректен, но допустим начин.

Пример за капсулиране в Java code:


public class Student {
private int age;
private String name;

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

public class Test{
public static void main(String[] args) {
Student firstStudent = new Student();
firstStudent.setName("John");
// The name field is private, so you can no longer do this:  firstStudent.name = "John"; 
}
}

Защо трябва да използвате капсулиране?

Основната причина е да улесните промяната на вашия code. Представете си, че имате заявление за учorще по хокей и има клас HockeyStudent с две полета, които съхраняват името и възрастта на ученика, когато той or тя се е записал в учorщето. Нещо като това:

public class HockeyStudent {
public String name;
public  int ageOfEnrollment;
}
Полето ageOfEnrollment е публично, няма гетери or сетери... Този клас се използва от много други класове и всичко беше наред, докато някой разработчик не реши, че едно int поле не е достатъчно. Някои хокеисти в кохорта са почти една година по-възрастни от връстниците си, така че би било по-удобно да ги разделим на две групи в зависимост от месеца, в който са родени. Така че полето ageOfEnrollment трябва да се промени на int масив (int[][]) : първото число е за пълни години, а второто е за месеци. Сега трябва да преработите целия code, който използва класа Student ! Но ако възрастта ви за записванеполето е частно и имате гетери и сетери, тогава всичко е по-лесно. Ако изискването за задаване на възрастта на ученик се промени, просто актуализирайте логиката в метода за настройка setAgeOfEnrollment() и вашите класове могат да продължат да използват Student без ниHowви проблеми! Този пример е донякъде измислен, но се надявам, че обяснява защо използването на капсулиране е страхотна идея.

Наследство

Този принцип е по-лесен за разбиране дори без практически опит. Не се повтаряй (DRY) може да бъде мотото на концепцията за наследяване. Наследяването ви позволява да създадете дъщерен клас, който наследява полетата и методите на родителския клас, без да ги предефинирате. Разбира се, можете да замените полетата и методите на родителския клас в дъщерния клас, но това не е необходимост. Нещо повече, можете да добавяте нови състояния и поведения в дъщерния клас. Родителските класове понякога се наричат ​​суперкласове or базови класове, а дъщерните класове са известни като подкласове. Ключовата дума extends на Java се използва за прилагане на принципа на наследяване в codeа.

Как работи в Java:

  1. Създайте родителския клас.
  2. Създайте дъщерния клас, като използвате ключовата дума extends .
  3. В конструктора на класа Child използвайте метода super(parentField1, parentField2, ...), за да зададете полетата на родителя.

Конструкторът е специален метод, използван за инициализиране на новосъздаден обект. Конструкторът има същото име като името на своя клас. Има два типа конструктори: по подразбиране (конструктор без аргументи) и параметризиран конструктор. Един клас трябва да има поне един конструктор (има конструктор по подразбиране, ако не са дефинирани други конструктори) и може да има много от тях.

Всеки път, когато създавате нов обект, вие извиквате неговия конструктор. В горния пример правите това в този ред:


Student firstStudent = new Student();

Използвате ключовата дума new , за да извикате конструктора по подразбиране на класа Student : tudent() .

Някои правила:

  1. Един клас може да има само един родител.
  2. Един родителски клас може да има много дъщерни класове.
  3. Дъщерен клас може да има свои собствени дъщерни класове.

Пример за наследяване в Java code

Нека създадем телефонен клас.

public class Phone {
    int price;
    double weight;

// Constructor
public Phone(int price, double weight) {
        this.price = price;
        this.weight = weight;
    }

    void orderPhone(){
        System.out.println("Ordering phone...");
    }
}
Разбира се, има различни видове телефони, така че нека създадем два дъщерни класа: един за телефони с Android и втори за iPhone. След това ще добавим някои полета и методи, които родителят няма. И ще използваме super() за извикване на конструктори за инициализиране на полетата, които родителският клас има.

Пример за наследяване в Java


public class Android extends Phone {

// Some new fields     
String androidVersion;
int screenSize;

    String secretDeviceCode;

// Constructor 
    public Android(int price, double weight, String androidVersion, int screenSize, String secretDeviceCode) {
        super(price, weight); // Android inherits Phone’s fields

        //this - reference to the current object
        //super - reference to the parent object

        this.androidVersion = androidVersion;
        this.screenSize = screenSize;
        this.secretDeviceCode = secretDeviceCode;
    }

	// New Android-specific method, does not exist in the Phone class 
    void installNewAndroidVersion() {
        System.out.println("installNewAndroidVersion invoked...");

    }

}

public class IPhone extends Phone {
   
    boolean fingerPrint;

    public IPhone(int price, double weight, boolean fingerPrint) {
        super(price, weight);
        System.out.println("IPhone constructor was invoked...");
        this.fingerPrint = fingerPrint;
    }

    void deleteIPhoneFromDb() {
        System.out.println("deleteIPhoneFromDb invoked...");
    }

@Override // This is about polymorphism, see below
void orderPhone(){
        System.out.println("Ordering my new iPhone and deleting the old one...");
    }
}
И така, да повторим: в Java наследяването ви позволява да разширите клас с дъщерни класове, които наследяват полетата и методите на родителския клас. Това е отличен начин за постигане на повторно използване на codeа.

Полиморфизъм

Полиморфизмът е способността на даден обект да се трансформира, като приема различни форми or по-скоро действа по различни начини. В Java полиморфизмът обикновено се случва, когато препратка към родителски клас се използва за препратка към обект на дъщерен клас.

Какво означава това и How работи в Java:

Какво е полиморфизъм в Java? Като цяло това означава, че можете да използвате едно и също име на метод за различни цели. В Java има два вида полиморфизъм: преодоляване на метод (динамичен полиморфизъм) и претоварване на метод (статичен полиморфизъм).

Отмяна на метода

Можете да замените метода на родителския клас в дъщерен клас, принуждавайки го да работи по различен начин. Нека създадем родителски клас Musician с метод play() .

Пример за полиморфизъм в Java code


   public class Musician {
    String name;
    int age;

    // Default constructor
    public Musician() {
    }

    // Parameterized constructor
    public Musician(String name, int age) {
        this.name = name;
        this.age = age;
    }

    void play() {
        System.out.println("I am playing my instrument...");
    }
}
Различните музиканти използват различни инструменти. Нека създадем два детски класа: Пианист и Цигулар . Благодарение на полиморфизма, всеки ще изпълни своя собствена version на метода play() . Когато заменяте, можете да използвате анотацията @Override , но не е необходимо.

public class Pianist extends Musician {
    
    String favoritePianoType;

    public Pianist(String name, int age, String favoritePianoType) {
        super(name, age);
        this.favoritePianoType = favoritePianoType;
    }


    @Override
void play(){
        System.out.println("I am playing the piano...");
    }
}
Цигуларят може да бъде солист or член на оркестър. Нека вземем това предвид, когато заменяме нашия метод play() .

public class Violinist extends Musician { 
    boolean isSoloist; 

public Violinist(String name, int age, boolean isSoloist) {
            super(name, age);
            this.isSoloist = isSoloist;
        }


    @Override
void play(){
if (isSoloist) 
        System.out.println("I am playing the violin solo...");
else 
System.out.println("I am playing the violin in an orchestra...");

    }
}
Нека създадем Демо клас, в който ще създадем три обекта, по една инстанция на всеки от създадените по-рано класове. Ще видим Howви резултати ще получим.

public class Demo {
  public static void main(String[] args) {
  Musician musician = new Musician();
  Violinist violinist = new Violinist("John", 32, true);
  Pianist pianist = new Pianist("Glen", 30, "Acoustic"); 

  System.out.println("Musician said:");
  musician.play();
  System.out.println("Violinist said:");
  violinist.play();
  System.out.println("Pianist said:");
  pianist.play();
    }
}
Ето Howво получаваме:

Musician said:
I am playing my instrument...
Violinist said:
I am playing the violin solo…
Pianist said:
I am playing the piano...
Всеки цигулар и пианист е музикант, но не всеки музикант е виолист or пианист. Това означава, че можете да използвате метода на възпроизвеждане на музиканта, ако не е необходимо да създавате нов. Или можете да извикате метода на родителя от детето, като използвате ключовата дума super . Нека направим това в codeа на Pianist:

public class Pianist extends Musician {

    String favoritePianoType;
    
    @Override
    void play(){
        super.play();
        System.out.println("I am playing the piano...");
    }
}
Сега нека извикаме нашия метод main() в класа Demo . Ето резултата:

Musician said:
I am playing my instrument...
Violinist said:
I am playing the violin solo...
Pianist said:
I am playing my instrument...
I am playing the piano...

Претоварване на метода

Претоварването на метод означава използване на различни методи с едно и също име в един и същ клас. Те трябва да се различават по брой, ред or видове параметри. Да предположим, че един пианист може да свири на акустично пиано и на електрическо пиано. За да свири електрик, музикантът се нуждае от електричество. Нека създадем два различни метода play() . Първият е без параметри, за акустично пиано, а вторият е с параметър, който показва дали има ток.

public class Pianist extends Musician {

    String name;
    int age;
    String favoritePianoType;

    @Override
    void play(){
        super.play();
        System.out.println("I am playing the piano...");
    }
    void play(boolean isElectricity){
        if (isElectricity) {
            System.out.println("The electricity is on.");
            System.out.println("I am playing the piano...");
        }
        else System.out.println("I can't play this without electricity.");
    }
}
Между другото, можете да използвате първия метод play() във втория метод play(boolean) по следния начин:

void play(boolean isElectricity){
        if (isElectricity) {
            System.out.println("The electricity is on.");
            play();
        }
        else System.out.println("I can't play this without electricity.");
    }
Нека добавим няколко реда към нашия демонстрационен клас, за да демонстрираме нашето претоварване:

public class Demo {
    public static void main(String[] args) {

        Musician musician = new Musician();
        Violinist violinist = new Violinist("John", 23, true);
        Pianist pianist = new Pianist("Glen", 30, "Acoustic"); 

        System.out.println("Musician said:");
        musician.play();
        System.out.println("Violinist said:");
        violinist.play();
        System.out.println("Pianist said:");
        pianist.play();
        System.out.println("The pianist will now try the electric piano:");
        pianist.play(true);
        System.out.println("The electricity has been shut off. Now when trying the electric piano, the pianist says:");
        pianist.play(false);
    }
}
Ето резултата:

Musician said:
I am playing my instrument...
Violinist said:
I am playing the violin solo...
Pianist said:
I am playing my instrument...
I am playing the piano...
The pianist will now try the electric piano:
The electricity is on.
I am playing my instrument...
I am playing the piano...
The electricity has been shut off. Now when trying the electric piano, the pianist says:
I can't play this without electricity.
Java знае кой метод трябва да се използва въз основа на неговите параметри и типа на обекта. Това е полиморфизъм.

Абстракция

Когато дефинираме клас, ние се опитваме да изградим модел на нещо. Да предположим например, че пишем видео игра, наречена MyRacer с различни състезателни коли. Играчът може да избере един от тях и след това по-късно да го актуализира or да купи друг. И така... Какво е кола? Колата е доста сложно нещо, но ако се опитваме да създадем състезателна видео игра (за разлика от симулатор на шофиране), тогава не е нужно да описваме всичките хиляди зъбни колела и уплътнения, които съдържа. Имаме нужда от неговия модел, максимална скорост, маневрени характеристики, цена, цвят… И може би това е достатъчно. Това е моделът на кола за нашата игра. Да предположим, че по-късно в MyRacer 2 решим да добавим гуми, които влияят на управлението на пътя. Тук моделът е различен, защото добавихме повече детайли. Позволявам' s определят абстракцията на данни като процес на идентифициране само на важните (or необходими) характеристики на даден обект и игнориране на всички неуместни подробности. Има различни нива на абстракция. Например, ако сте пътник в автобус, трябва да знаете How изглежда вашият автобус и къде отива, но не е нужно да знаете How да го управлявате. Ако сте шофьор на автобус, не е нужно да знаете How да създадете нов автобус — трябва само да знаете How да го управлявате. Но ако сте производител на автобуси, трябва да отидете на по-ниско ниво на абстракция, защото детайлите на дизайна на автобуса са много важни за вас. Надявам се разбирате Howво имам предвид. трябва да знаете How изглежда вашият автобус и накъде отива, но не е нужно да знаете How да го управлявате. Ако сте шофьор на автобус, не е нужно да знаете How да създадете нов автобус — трябва само да знаете How да го управлявате. Но ако сте производител на автобуси, трябва да отидете на по-ниско ниво на абстракция, защото детайлите на дизайна на автобуса са много важни за вас. Надявам се разбирате Howво имам предвид. трябва да знаете How изглежда вашият автобус и накъде отива, но не е нужно да знаете How да го управлявате. Ако сте шофьор на автобус, не е нужно да знаете How да създадете нов автобус — трябва само да знаете How да го управлявате. Но ако сте производител на автобуси, трябва да отидете на по-ниско ниво на абстракция, защото детайлите на дизайна на автобуса са много важни за вас. Надявам се разбирате Howво имам предвид.

Как работи в Java:

Нека изградим четири нива на абстракция в Java, or по-скоро в ООП — от най-ниското (най-специфичното) до най-високото (най-абстрактното).
  1. Най-ниското ниво на абстракция е конкретен обект. Това е образувание с набор от характеристики, които принадлежат към определен клас. Има специфични стойности на полето

  2. Шаблон за създаване на обекти е клас. Това е описание на набор от обекти с подобни свойства и вътрешна структура.

  3. Абстрактният клас е абстрактно описание на характеристиките на набор от класове (той действа като шаблон за наследяване от други класове). Той има високо ниво на абстракция, така че е невъзможно да се създават обекти директно от абстрактен клас. Само дъщерни класове на абстрактни класове могат да се използват за създаване на обекти. Абстрактен клас може да включва методи с имплементация, но това не е изискване.

  4. Интерфейсът е конструкция на конструкцията на езика за програмиране Java, която съдържа само абстрактни публични методи и статични константни полета (крайна статика). С други думи, нито абстрактните класове, нито интерфейсите могат да се използват за генериране на обекти.

Между другото, в Java 8 or по-нова version интерфейсите могат да имат не само абстрактни методи и константи, но и методи по подразбиране и статични. В Java интерфейс дефинира поведение, докато абстрактен клас се използва за създаване на йерархия. Един интерфейс може да бъде реализиран от множество класове.

Пример за интерфейс в Java code


interface Human {
	public void struggle();
	public void protect();
}

interface Vulcan {
	int angleOfPointyEars; 
	public void turnOffEmotions(boolean isOn);
	public void telepathy();
}
Можете да внедрите повече от един интерфейс

The Spock class implements Human and Vulcan {
public void struggle() {
System.out.println("I am struggling...");
}
	public void protect() {
System.out.println("You are under my protection!”);
}
public void turnOffEmotions(boolean isOn){
If (isOn) {
System.out.println("I am turning off my emotions.");
isOn= !isOn;
}
}
	public void telepathy() {
System.out.println("Connecting to your brain...");
}

}
За начинаещи студенти, това обхваща всички основни концепции на обектно-ориентираното програмиране в Java. Освен 4-те основни ООП принципа, Java също има асоцииране, агрегиране и композиция. Можете да ги наречете „допълнителни OOP принципи“. Те заслужават отделна статия.
Коментари
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION