Абстракция в Java?

Сегодня я услышал от своего друга, что инкапсуляция — это не только скрытие информации, но и абстракция. Как это достигается?

public class employee {

     private String name;
     private int id;

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

     public String getName(){
         return name;
     }
}

В приведенном выше примере достигается инкапсуляция, когда я разрешаю классу доступ к моему публичному методу, а не к закрытым членам, но при чем тут абстракция? Может ли кто-нибудь объяснить мне абстракцию немного ясным образом.


person John Cooper    schedule 02.09.2011    source источник


Ответы (11)


Есть две разные вещи: сокрытие информации и абстракция.

Сокрытие информации делает возможной абстракцию, но это нечто иное. Например, используя ваш код

public class employee {

     private String name;
     private int id;

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

     public String getName(){
         return name;
     }
}

Поле id на самом деле скрыто. Это позволяет обрабатывать идентификаторы способом, не связанным с остальной частью программы. Ваше поле имени на самом деле тоже скрыто, так как вы не имеете прямого доступа к полю имени, но код в getName и setName делает это.

Как только вы скроете структуру данных от остального кода, обеспечив доступ через методы, можно создать ряд заменяемых реализаций элемента. Например, employee — это концептуальный вид person, поэтому вы могли бы переписать приведенное выше так:

public interface Person {
     public abstract String getName();
}

public class Employee implements Person {

     private String name;
     private int id;

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

     public String getName(){
         return name;
     }
}

Теперь ваш код может обрабатывать Employee как Person. После переписывания остального кода, который явно не работает с Employee, для работы с Person, вы можете реализовать другие виды Person и использовать задачи, не относящиеся к сотрудникам, которые теперь являются задачами Person.

public Customer implements Person {
     private String name;
     private integer moneySpent;

     public String getName() {
          return name;
     }
}

Таким образом, процедура поиска человека, пока она индексирует только объекты Person, теперь может включать поиск как Employees, так и Customers. Это связано с тем, что код, работающий с объектами Person, на самом деле имеет дело с абстракцией более высокого уровня, которую разделяют как объекты Employee, так и объекты Customer.

При работе с объектами на абстрактном уровне имена методов являются общими для всей абстракции; но фактически выполняемый код зависит от неупомянутого базового типа объекта. Другими словами, если вы спросите человека (который оказался сотрудником) getName(), он ответит функцией Employee.getName(), а Customer ответит функцией Customer.getName(). Поскольку код, вызывающий getName(), работает с Persons, он понятия не имеет, с каким типом людей он будет работать, но очевидное изменение в поведении (выбор правильного блока кода для каждого объекта) все же происходит. Это явление известно как полиморфизм, и если вы впервые столкнулись с этими понятиями, вы услышите, что слово «полиморфизм» часто используется.

Пример полиморфного поведения:

 public interface Animal {
     public abstract String makeSound();
 }

 public class Cow implements Animal {
     public String makeSound() {
         return "Moo Moo!";
     }
 }

 public class Dog implements Animal {
     public String makeSound() {
         return "Ruff Ruff!";
     }
 }

 public class Sheep implements Animal {
    public String makeSound() {
         return "Baa Baa!";
    }
 }

 // this class demonstrates the polymorphic behavior

 public class Farm {
    public static void main(String[] args) {
       ArrayList<Animal> animals = new ArrayList<Animal>();
       animals.add(new Cow());
       animals.add(new Sheep());
       animals.add(new Dog());

       for (Animal animal : animals) {
          // this is where the polymorphisim occurs
          // each animal will make a different sound
          // because the makeSound method is getting
          // bound to different blocks of code based
          // on the exact type of animal class hiding
          // under the Animal abstraction.
          System.out.println(animal.makeSound());
       }
    }
 }

ожидаемый результат:

 Moo Moo!
 Baa Baa!
 Ruff Ruff!

хотя мы никогда явно не меняли классы и никогда явно не меняли методы. Изменялась привязка абстрактного метода к явному подклассу, что происходит только в системах, поддерживающих полиморфизм.

person Edwin Buck    schedule 02.09.2011
comment
@edwin ... удалил комментарий во время комментирования, я только что видел код ... мне очень жаль. еще раз очень жаль... - person amod; 02.09.2011
comment
пожалуйста, завершите свой ответ... из приведенного выше описания, где вы можете сделать вывод, что инкапсуляция достигает абстракции... есть некоторые моменты, где я это вижу. Но это для Джона. Он должен четко понимать концепцию. - person amod; 02.09.2011
comment
Нет, инкапсуляция не приводит к абстракции. Это делает возможной абстракцию. Чтобы увидеть человека, нужно игнорировать различия и сосредоточиться только на общих чертах, таких как рост и возраст. У каждого человека есть рост и возраст (общие черты), но не у всех есть золотые карманные часы моего деда или моя перьевая ручка (различия). Если мы не можем инкапсулировать дифференциаторы, то абстракция становится очень сложной, поскольку нет разделения дифференциаторов от общих черт, и код, работающий с общими чертами, может обманывать, обращаясь к дифференциаторам, чтобы действительно выполнять свою работу. - person Edwin Buck; 02.09.2011

@ Джон, ваш друг прав, реализуя инкапсуляцию, вы также достигаете абстракции.

public class employee {
       private String name;
       private int id;   
       public void setName(String name){ 
         name= name+"something that you want to edit";
         this.name = name;      }   
       public String getName(){  
        return name;      }
   } 

таким образом, вы отредактировали метод ur set и скрыли детали от пользователя, который является не чем иным, как абстракцией... таким образом, написав геттеры и сеттеры, вы скрываете пользователя для выполнения ненужной задачи...

public void setName(String name){ 
         /*some internal logic suppose in database you want name 
         *should be added with its id but what user to do with it.*/
         this.name = name;      }   
       public String getName(){  
        /* now suppose you have recieved the name from
        *data base it has id but you want user to know only 
        name then you will write the logic here to show the name.*/
        return name;      }

Я знаю, что добавление идентификатора к имени - глупый пример, но это то, о чем я могу думать прямо сейчас... но учтите, что для очень большого проекта вы много раз пишете код в наборе (или вызываете другой метод, который изменяет его параметры), тогда что ... предположим, вы получили имя, но хотите сохранить его в зашифрованном виде в db, тогда что. Пользователя не волнует шифрование, но да, вы должны... потому что оно не нужно пользователю, но важно для вас. Так что это должно быть в вашем коде, но скрыто от пользователя, и в этом вся суть абстракции * («СКРЫТИЕ НЕНУЖНЫХ ДАННЫХ ОТ ПОЛЬЗОВАТЕЛЯ») *

EDITED: - Перейти к источнику! Грэди Буч говорит (в «Объектно-ориентированном анализе и проектировании», стр. 49, второе издание):

«Абстракция и инкапсуляция являются взаимодополняющими понятиями: абстракция фокусируется на наблюдаемом поведении объекта... инкапсуляция фокусируется на реализации, которая приводит к такому поведению... инкапсуляция чаще всего достигается за счет сокрытия информации, то есть процесса сокрытия всего секретов объекта, которые не способствуют его существенным характеристикам».

сверху можно сделать такой же вывод

person amod    schedule 02.09.2011
comment
@downvoter... по ошибке я опубликовал, не написав весь ответ, пожалуйста, посмотрите сейчас... - person amod; 02.09.2011

Я думаю, что он путает полиморфизм с инкапсуляцией. Полиморфизм может помочь вам достичь абстракции.

person bittersweetryan    schedule 02.09.2011

Здесь в основном инкапсуляция, но есть и некоторая абстракция. При использовании метода с именем setName() коду, использующему ваш класс, не нужно знать, как вы реализуете операцию «установки имени». Насколько им известно, вы обращаетесь к веб-сервису и устанавливаете его где-то в базе данных. Или, может быть, вы полностью игнорируете параметр и каждый раз устанавливаете имя «Стивен». Эти факты абстрагируются от вызывающего абонента.

person dlev    schedule 02.09.2011

Я не думаю, что вы можете доказать инкапсуляцию на этом конкретном примере. Это больше похоже на это:

interface NameService {
    String getName();
}

Теперь скажите мне: класс, реализующий этот интерфейс, получает имя из плоского файла, базы данных, хранилища nosql или откуда-то еще?

person Kevin    schedule 02.09.2011

Абстракция — это концепция/модель, которая не может быть реализована/реализована как таковая. Абстракция - это ограничение поведения метода/членов объекта для других классов.

person MduSenthil    schedule 02.09.2011

Лично я бы не сказал, что инкапсуляция на самом деле связана с абстракцией (хотя я понимаю, как это можно понимать таким образом), она заключается только в том, чтобы позволить пользователю видеть или делать то, что необходимо — он видит только интерфейс для класс, а не его внутреннее устройство. В вашем случае это достигается, потому что вы только устанавливаете или получаете имя определенного класса, вы никогда не обращаетесь к переменной имени напрямую и никогда не видите, как она хранится. Таким образом, вы можете изменить имя или тип переменной имени на что-то совершенно другое, и интерфейс вашего класса все равно будет работать и выглядеть так же. Я предполагаю, что это можно было бы принять в некотором смысле как абстракцию.

Определения расплывчаты, но я считаю, что полиморфизм больше относится к сфере абстракции, где вы отделяете реализацию (скажем, ArrayList) от интерфейса, который она наследует (скажем, List). Таким образом, вы просто имеете дело со списком интерфейсов. , и базовый список может быть чем угодно, но это деталь реализации, и поскольку вы находитесь на абстрактном уровне «выше» этого, вам не нужно об этом беспокоиться. Конечно, это упрощение, иногда вам нужно знать детали реализации из соображений производительности или если некоторые операции могут быть не реализованы или разрешены в вашей конкретной реализации. Но с расплывчатой ​​точки зрения (и чисто объектно-ориентированной точки зрения) это верно.

Что бы вы это ни понимали, самое главное, вы понимаете логику, стоящую за этим, почему это хорошая идея и почему всегда лучше делать что-то именно так (в этом случае, иметь поля как приватные и использовать геттеры/сеттеры для доступа их.)

person Michael Berry    schedule 02.09.2011

но при чем тут абстракция?

вы сами сказали: «разрешить классу доступ к моему общедоступному методу, а не к закрытым членам» или, другими словами: разрешить другим классам доступ к тому, к чему они могут получить доступ, и защитить то, к чему они не могут.

абстракция здесь исходит из общедоступных методов, например, в getName() вам не нужно всегда указывать значение частного члена, к нему можно добавить другое значение или даже он может дать совершенно другое. это все равно, что сказать: "скажи мне свое имя, как бы ты его мне не назвал". возможно, лучшим примером был бы метод с именем getYourWorkDone(). принцип остается прежним: "делай свою работу! как? мне все равно, как!"

часть инкапсуляции принадлежит частным членам. этот класс инкапсулирует эти частные члены, поэтому они сгруппированы для формирования состояния класса.

person LeleDumbo    schedule 02.09.2011


Кажется, инкапсуляция и абстракция запутали всех. Если вы спросите меня, это совершенно разные темы, и в этом нет абсолютно никакой путаницы.

абстракция происходит, когда вы используете ключевое слово «abstract», а инкапсуляция происходит, когда вы создаете класс. хорошая реализация инкапсуляции включает в себя приватность всех ваших элементов данных.

Я написал несколько сообщений в блоге, которые могут вам помочь:

Узнайте, как использовать абстрактный класс в объектно-ориентированном дизайне

Теория абстракции

person Navin Israni    schedule 31.10.2016

Абстракция выполняется, когда вы хотите скрыть данные. В то время как инкапсуляция выполняется, когда вы хотите скрыть как данные, так и код. Это упаковка как данных, так и кода, которые вы реализуете.

Вы можете реализовать абстракцию, используя абстрактный класс или интерфейс. В абстрактном классе мы можем писать конкретные методы или абстрактные методы, но в интерфейсе мы можем использовать только абстрактные методы.

Вы можете реализовать инкапсуляцию, используя модификаторы доступа, такие как public, protected, private. Эти модификаторы доступа контролируют доступ к вашим данным, то есть должны ли они быть общедоступными (могут быть видны всем), защищенными (доступны только расширенным классам) или частными (скрывать их от всех).

person Sahithya    schedule 07.06.2019