Как именно «Объекты общаются друг с другом, передавая сообщения»? - PullRequest
21 голосов
/ 27 февраля 2010

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

Из википедии "В ООП каждый объект способен принимать сообщения , обрабатывать данные и отправлять сообщения другим объектам и может рассматриваться как независимый" компьютер " отдельная роль или ответственность. "

Что именно означает это утверждение в коде?

class A
{ 
    methodA()
    {

    }
}


class B
{
    methodB()
    {

    }
}


class C
{
    main()
    {
        A a=new A();
        B b=new B();
        a.methodA(); // does this mean msgs passing??
        b.methodB(); // or does this?? I may be completely off-track here..
    }
}

Ответы [ 10 ]

23 голосов
/ 27 февраля 2010

Если мы говорим об ООП, то термин "передача сообщений" происходит от Smalltalk . В нескольких словах основные принципы Smalltalk:

  1. Объект является базовой единицей объектно-ориентированной системы.
  2. Объекты имеют свое собственное состояние .
  3. Объекты взаимодействуют, отправляя и получая сообщения .

Если вы заинтересованы в Smalltalk, взгляните на Pharo или Squeak .

Java / C # / C ++ и многие другие языки используют немного другой подход, вероятно, полученный из Simula . Вы вызываете метод вместо передачи сообщения.

Я думаю, что эти термины более или менее эквивалентны. Единственным интересным отличием может быть то, что передача сообщений (по крайней мере в Smalltalk) всегда зависит от динамической диспетчеризации и поздней привязки, тогда как в случае вызова метода можно использовать статическую диспетчеризацию и раннюю привязку. Например, C ++ (AFAIK) выполняет раннее связывание по умолчанию, пока где-то не появится ключевое слово «virtual» ...

В любом случае, независимо от того, какой формализм использует ваш язык программирования для связи между двумя объектами (передача сообщений или вызов метода), всегда считается хорошим стилем ООП, чтобы запретить прямой доступ к переменным экземпляра в терминологии Smalltalk или к членам данных в терминологии C ++ или какой бы термин не использовался в вашем языке программирования.

Smalltalk напрямую запрещает доступ к переменным экземпляра на уровне синтаксиса. Как я уже упоминал выше, объекты в программе Smalltalk могут взаимодействовать только путем передачи / получения сообщений. Многие другие языки разрешают доступ к переменным экземпляра на уровне синтаксиса, но это считается плохой практикой. Например, знаменитая книга Effective C ++ содержит соответствующую рекомендацию: Элемент 22: Объявление элементов данных личными.

Причины:

  • синтаксическая согласованность (единственный способ для клиентов получить доступ к объекту через функции-члены или передачу сообщений);
  • более точный контроль доступности элементов данных (вы можете реализовать отсутствие доступа, доступ только для чтения, доступ для чтения и записи и даже доступ только для записи);
  • вы можете позже заменить элемент данных, не нарушая ваш публичный интерфейс.

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

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

(с) Скотт Мейерс, Эффективный C ++: 55 конкретных способов улучшить ваши программы и разработки (3-е издание)

9 голосов
/ 27 февраля 2010

Не совсем ответ на ваш вопрос, но небольшое отступление о отправке сообщений и вызове метода :

Термин message относится к тому факту, что вы не знаете , какой метод будет вызываться из-за полиморфизма. Вы просите объект сделать что-то (отсюда термин message ), и он действует соответственно. Термин метод invocation вводит в заблуждение, поскольку он предлагает вам выбрать один точный метод.

Термин message также ближе к реальности динамического языка, где вы можете на самом деле отправить сообщение, которое объект не понимает (см. doesNotUnderstand в Smalltalk). В этом случае вы не можете говорить о вызове метода, если не найдено ни одного совпадения, и отправка сообщения завершится неудачно. В статическом типизированном языке эта проблема предотвращена.

8 голосов
/ 27 февраля 2010

«Передача сообщения» является абстракцией.

Большинство языков OO сегодня реализуют эту абстракцию в форме вызова функций. Под особенностью я подразумеваю метод операцию (см. Правку ниже), свойство или что-то подобное. Бертран Мейер (Bertrand Meyer) в статье OOSC2 утверждает, что вызов функции является базовой единицей вычисления в современных языках OO; это совершенно правильный и последовательный способ реализовать старую абстрактную идею о том, что «объекты взаимодействуют посредством передачи сообщений».

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

В заключение: не путайте абстракции с кодом. В старину программисты очень заботились о теории, потому что программирование едва ли было основной профессией. Сегодня большинство программистов редко знакомы с теорией кода. : -)

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

Редактировать . В большинстве ОО-языков вы называете операции, а не методы. Это двигатель времени выполнения, который решает, какой конкретный метод вызывать в ответ на вызванную вами операцию. Это позволяет реализовать так часто упоминаемые механизмы полиморфизма. Этот маленький нюанс обычно забывают на обычном языке, когда мы ссылаемся на «вызов метода». Однако необходимо проводить различие между операциями (как функциями, реализующими передачу сообщений) и методами (как конкретными версиями указанных операций).

5 голосов
/ 27 февраля 2010

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

Клиентский объект не может напрямую манипулировать состоянием принимающего объекта. Это является преимуществом инкапсуляции - принимающий объект может самостоятельно реализовывать свое собственное состояние и изменять его реализацию, не влияя на то, как клиенты взаимодействуют с ним.

4 голосов
/ 27 февраля 2010

В ООП объекты не обязательно связываются друг с другом путем передачи сообщений.Они общаются друг с другом некоторым способом, который позволяет им указывать, что они хотят сделать, но оставляет реализацию этого поведения принимающему объекту.Передача сообщения является одним из способов достижения такого отделения интерфейса от реализации.Другой способ заключается в вызове (виртуального) метода в принимающем объекте.

Что касается того, какие из ваших вызовов функций-членов действительно соответствуют этим требованиям, сказать немного сложно в зависимости от языка.Например, в Java функции-члены по умолчанию являются виртуальными, поэтому ваши вызовы a.methodA() и b.methodB() будут эквивалентны передаче сообщения.Ваши (попытки a) вызовы b.methodA() и a.methodB() не будут компилироваться, потому что Java статически типизирована.

Напротив, в C ++ функции-члены по умолчанию не виртуальныетак что ни один из ваших звонков не эквивалентен передаче сообщений.Чтобы получить что-то эквивалентное, вам нужно явно объявить, по крайней мере, одну из функций-членов как виртуальную:

class A { 
    virtual void methodA() {}
};

Как бы то ни было, в сущности, это «различие без разницы».Чтобы получить представление о том, что это значит, вам нужно использовать наследование:

struct base { 
    void methodA() { std::cout << "base::methodA\n"; }
    virtual void methodB() { std::cout << "base::methodB\n"; }
};

struct derived { 
    void methodA() { std::cout << "derived::methodA\n"; }
    virtual void methodB() { std::cout << "derived::methodB"; }
};

int main() { 
    base1 *b1 = new base;
    base2 *b2 = new derived;

    b1->methodA();   // "base::methodA"
    b1->methodB();   // "base::methodB"
    b2->methodA();   // "base::methodA"
    b2->methodB();   // "derived::methodB"
    return 0;
}
1 голос

передача объекта в качестве параметра методу объекта, принадлежащего другому типу класса.таким образом, вы передаете атрибут объекта другому объекту другого класса, просто вызывая методы объекта другого класса.так что вы можете создать объект этого класса, чтобы получить информацию о другом объекте другого класса.Примечание: это не метод переопределения в порядке, потому что они могут иметь одинаковые имена, но принадлежать к другому типу класса.Переопределение методов - это то, что вы наследуете методы в подклассе и изменяете поведение тех же методов, которые вы получаете для наследования суперкласса.вызываемый метод зависит от аргументов, которые вы указали в методе или типе данных.система вызывает правильный метод, и они могут быть расположены в объекте суперкласса или в объекте подкласса.

многие люди задают один и тот же вопрос.когда они работают с ООП.Я рекомендую прочитать эти старые книги.понимать, что такое ООП, а не учиться объектам программирования, ориентированным на язык программирования, такой как CPP, JAVA и PHP.введение в ООП (Тимоти Бууд) объектно-ориентированного программирования: эволюционный подход (Брэд Дж. Кокс. Эндрю Дж. Новобилски) и не забудьте прочитать новые книги Бьярне Страуструп CPP.

#include <iostream>
#include <string>
using namespace std;

class Car{
string brand;   
public:
void setBrand(string newBrand){this->brand=newBrand;}
void Driver(){cout<<" IS DRIVING THIS CAR BRAND "<<brand<<endl;}
void Brake(){cout<<"IS BRAKING"<<endl;}
};

class Person{
private:string name;
public:
void setName(string newName){this->name=newName;}
//HERE WE CALL METHOD OF CAR CLASS AND REDEFINE METHODS NO OVERRIDE OK   
void Driver(Car objectOfClassCar){cout<<this->name<<ends;  
objectOfClassCar.Driver();}
 void Brake(string str, Car objectOfClassCar){cout<<this->name<<"  
"<<str<<ends;objectOfClassCar.Brake();}
  };

  int main(){
  Car corolla;
  corolla.setBrand("TOYOTA");   
  Person student;
  student.setName("MIGUEL");
  student.Driver(corolla);
  student.Brake("CAR",corolla);
  //it open a lot of opportunities to do the same.
  }
1 голос
/ 27 февраля 2010

Некоторые из ранних академических работ по ОО были связаны с тем, что объекты передавали сообщения друг другу, чтобы вызвать поведение. Некоторые ранние ОО-языки были написаны таким образом (SmallTalk?).

Современные языки, такие как C ++, C # и Java, вообще не работают таким образом. У них просто есть методы вызова кода на объектах. Это очень похоже на процедурный язык, за исключением того, что в вызове передается скрытая ссылка на вызываемый класс ("this").

1 голос
/ 27 февраля 2010

Ваш пример не будет работать с Java или Python, поэтому я исправил и аннотировал ваш основной

class C{
  main()
  {
   A a=new A();
   B b=new B();
   a.methodA(); // C says to a that methodA should be executed
   // C says to b that methodB should be executed
   // and b says to C that the result is answer
   answer = b.methodB(); 
  }
}
1 голос
/ 27 февраля 2010

То, что вы опубликовали, не будет компилироваться ни на одном языке, так как methodB не принадлежит объекту A, а methodA не принадлежит объекту B.

Если вы вызвали правильный метод, то оба они являются передачей сообщений объектом C:

a.methodA();
b.methodB();

Из википедии:

The process by which an object sends data to another object or asks the other object to invoke a method.

0 голосов
/ 27 февраля 2010

Этот код работает?

В любом случае, вы вне дороги ...

Передача сообщений - это способ межпроцессного взаимодействия, один из многих. Это означает, что два (или более) объекта могут говорить друг с другом только посредством обмена сообщениями, в которых должно быть сказано, кто, кому и что ...

Вы видите, что он сильно отличается от разделяемой памяти, например ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...