рдЯреАрдо рд╡рд┐рдХрд╛рд╕ рдХреЗ рдЖрдзрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдпрддрд╛ рдФрд░ рд╡рд┐рд╢реНрд╡рд╛рд╕ рдХрд╛ рднреНрд░рдо

рдЖрдо рддреМрд░ рдкрд░ рдореИрдВ рдПрдХ C ++ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рд╣реВрдВред рдЦреИрд░ рдпрд╣ рддреЛ рд╣реБрдЖред рдореЗрд░реЗ рджреНрд╡рд╛рд░рд╛ рдЕрдкрдиреЗ рдХреИрд░рд┐рдпрд░ рдореЗрдВ рд▓рд┐рдЦреЗ рдЧрдП рдЕрдзрд┐рдХрд╛рдВрд╢ рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рдХреЛрдб C ++ рд╣реИрдВред рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рднрд╛рд╖рд╛ рдХреЗ рдкреНрд░рддрд┐ рдЕрдкрдиреЗ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдЕрдиреБрднрд╡ рдХреЗ рдРрд╕реЗ рдордЬрдмреВрдд рдкреВрд░реНрд╡рд╛рдЧреНрд░рд╣ рдХреЛ рдкрд╕рдВрдж рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реВрдВ, рдФрд░ рдореИрдВ рдХреЛрд╢рд┐рд╢ рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рдХрд┐рд╕реА рдЕрдиреНрдп рднрд╛рд╖рд╛ рдореЗрдВ рдХреБрдЫ рд▓рд┐рдЦрдиреЗ рдХрд╛ рдЕрд╡рд╕рд░ рди рдЪреВрдХреЗрдВред рдФрд░ рдореЗрд░реЗ рд╡рд░реНрддрдорд╛рди рдирд┐рдпреЛрдХреНрддрд╛ рдиреЗ рдЕрдЪрд╛рдирдХ рдРрд╕рд╛ рдЕрд╡рд╕рд░ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛: рдореИрдВрдиреЗ рдЬрд╛рд╡рд╛ рдореЗрдВ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рддреБрдЪреНрдЫ рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдирд╣реАрдВ рдмрдирд╛рдиреЗ рдХрд╛ рдЙрдкрдХреНрд░рдо рдХрд┐рдпрд╛ред рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рднрд╛рд╖рд╛ рдХрд╛ рдЪреБрдирд╛рд╡ рдРрддрд┐рд╣рд╛рд╕рд┐рдХ рдХрд╛рд░рдгреЛрдВ рд╕реЗ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рдореБрдЭреЗ рдХреЛрдИ рдЖрдкрддреНрддрд┐ рдирд╣реАрдВ рдереАред рдЬрд╛рд╡рд╛ рдЗрддрдирд╛ рдЬрд╛рд╡рд╛, рдореЗрд░реЗ рд▓рд┐рдП рдХрдо рдкрд░рд┐рдЪрд┐рдд - рдмреЗрд╣рддрд░ред

рдЕрдиреНрдп рдмрд╛рддреЛрдВ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рд╕рд░рд▓ рдХрд╛рд░реНрдп рдерд╛: рдПрдХ рдмрд╛рд░ рддрд╛рд░реНрдХрд┐рдХ рд░реВрдк рд╕реЗ рдЬреБрдбрд╝реЗ рдбреЗрдЯрд╛ рдХрд╛ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕реЗрдЯ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдФрд░ рдЗрд╕реЗ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдЙрдкрднреЛрдХреНрддрд╛ рдХреЛ рд╣рд╕реНрддрд╛рдВрддрд░рд┐рдд рдХрд░рдирд╛ред рдХрдИ рдЙрдкрднреЛрдХреНрддрд╛ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдЗрдирдХреИрдкреНрд╕реБрд▓реЗрд╢рди рд╕рд┐рджреНрдзрд╛рдВрдд рдХреЗ рдЕрдиреБрд╕рд╛рд░, рд╕рдВрдЪрд╛рд░рдг рдХреЛрдб (рдирд┐рд░реНрдорд╛рддрд╛) рдХреЛ рдпрд╣ рдкрддрд╛ рдирд╣реАрдВ рд╣реИ рдХрд┐ рд╕реНрд░реЛрдд рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдХреНрдпрд╛ рд╣реИ рдФрд░ рдпрд╣ рдХреНрдпрд╛ рдХрд░ рд╕рдХрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдирд┐рд░реНрдорд╛рддрд╛ рдХреЛ рдкреНрд░рддреНрдпреЗрдХ рдЙрдкрднреЛрдХреНрддрд╛ рдХреЛ рд╕рдорд╛рди рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдореИрдВ рдкреНрд░рддрд┐рдпрд╛рдБ рдмрдирд╛рдирд╛ рдФрд░ рдЙрдиреНрд╣реЗрдВ рджреЗрдирд╛ рдирд╣реАрдВ рдЪрд╛рд╣рддрд╛ рдерд╛ред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рд╣рдореЗрдВ рдХрд┐рд╕реА рддрд░рд╣ рдЙрдкрднреЛрдХреНрддрд╛рдУрдВ рдХреЛ рдЙрдирдХреЗ рджреНрд╡рд╛рд░рд╛ рдкреНрд░реЗрд╖рд┐рдд рдбреЗрдЯрд╛ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рдЕрд╡рд╕рд░ рд╕реЗ рд╡рдВрдЪрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред

рдпрд╣ рддрдм рдерд╛ рдХрд┐ рдЬрд╛рд╡рд╛ рдореЗрдВ рдореЗрд░реА рдЕрдиреБрднрд╡рд╣реАрдирддрд╛ рдиреЗ рдЦреБрдж рдХреЛ рдорд╣рд╕реВрд╕ рдХрд┐рдпрд╛ред C ++ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдореБрдЭреЗ рднрд╛рд╖рд╛ рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреА рдХрдореА рдереАред рд╣рд╛рдВ, final рдХреАрд╡рд░реНрдб рд╣реИ, рд▓реЗрдХрд┐рди final Object C ++ рдореЗрдВ Object* const рддрд░рд╣ рд╣реИ, const Object* ред рдпрд╛рдиреА final List<String> рдЖрдк рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреЛ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ C ++ рд╡реНрдпрд╡рд╕рд╛рдп рд╣реИ: рдорд╛рдпрд░реНрд╕ рдЯреЗрд╕реНрдЯрд╛рдореЗрдВрдЯ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд╣рд░ рдЬрдЧрд╣ рдХрд╛рд╕реНрдЯ рдХрд░рдирд╛, рдФрд░ рдпрд╣ рдмрд╛рдд рд╣реИ! рдХреЛрдИ рдХреБрдЫ рдирд╣реАрдВ рдмрджрд▓реЗрдЧрд╛ред рддреЛ? рдЦреИрд░, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдирд╣реАрдВред рдореИрдВрдиреЗ рдЕрдкрдиреЗ рдЕрд╡рдХрд╛рд╢ рдкрд░ рдЙрд╕ рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдХреЛ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдереЛрдбрд╝рд╛ рд╕реЛрдЪрд╛, рдФрд░ рдЬреЛ рдореИрдВ рдЖрдпрд╛ рдерд╛ред

рд╕реА ++


рдореБрдЭреЗ рдЖрдкрдХреЛ рд╕реНрд╡рдпрдВ рдХрд╛рд░реНрдп рдпрд╛рдж рджрд┐рд▓рд╛рдиреЗ рджреЗрдВ:

  1. рдПрдХ рдмрд╛рд░ рдбреЗрдЯрд╛ рд╕реЗрдЯ рдмрдирд╛рдПрдВред
  2. рдХрд┐рд╕реА рднреА рдЪреАрдЬ рдХреА рдЕрдирд╛рд╡рд╢реНрдпрдХ рд░реВрдк рд╕реЗ рдирдХрд▓ рди рдХрд░реЗрдВред
  3. рдЙрдкрднреЛрдХреНрддрд╛ рдХреЛ рдЗрд╕ рдбреЗрдЯрд╛ рдХреЛ рдмрджрд▓рдиреЗ рд╕реЗ рд░реЛрдХреЗрдВред
  4. рдХреЛрдб рдХрдо рд╕реЗ рдХрдо рдХрд░реЗрдВ, рдЕрд░реНрдерд╛рдд рдкреНрд░рддреНрдпреЗрдХ рдбреЗрдЯрд╛ рд╕реЗрдЯ рдХреЗ рд▓рд┐рдП рддрд░реАрдХреЛрдВ рдФрд░ рдЗрдВрдЯрд░рдлреЗрд╕ рдХрд╛ рдПрдХ рдЧреБрдЪреНрдЫрд╛ рди рдмрдирд╛рдПрдВ, рдЬреЛ рдХрд┐ рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рд╕рд┐рд░реНрдл рдПрдХ-рджреЛ рд╕реНрдерд╛рдиреЛрдВ рдкрд░ рд╣реЛред

рдмрд╣реБрд╡рд┐рдХрд▓реНрдкреАрдп рд╕реНрдерд┐рддрд┐ рдЬреИрд╕реЗ рдЕрдкрд╡рд╛рджреЛрдВ рдХреЗ рдЕрд░реНрде рдореЗрдВ рд╕реБрд░рдХреНрд╖рд╛, рд╕реБрд░рдХреНрд╖рд╛ рдЖрджрд┐ рдирд╣реАрдВред рд╕рд░рд▓рддрдо рдорд╛рдорд▓реЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред рдпрд╣рд╛рдБ рд╣реИ рдХрд┐ рдореИрдВ рдЗрд╕реЗ рд╕рдмрд╕реЗ рдкрд░рд┐рдЪрд┐рдд рднрд╛рд╖рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░реВрдВрдЧрд╛:

foo.hpp
 #pragma once #include <iostream> #include <list> struct Foo { const int intValue; const std::string strValue; const std::list<int> listValue; Foo(int intValue_, const std::string& strValue_, const std::list<int>& listValue_) : intValue(intValue_) , strValue(strValue_) , listValue(listValue_) {} }; std::ostream& operator<<(std::ostream& out, const Foo& foo) { out << "INT: " << foo.intValue << "\n"; out << "STRING: " << foo.strValue << "\n"; out << "LIST: ["; for (auto it = foo.listValue.cbegin(); it != foo.listValue.cend(); ++it) { out << (it == foo.listValue.cbegin() ? "" : ", ") << *it; } out << "]\n"; return out; } 


api.hpp
 #pragma once #include "foo.hpp" #include <iostream> class Api { public: const Foo& getFoo() const { return currentFoo; } private: const Foo currentFoo = Foo{42, "Fish", {0, 1, 2, 3}}; }; 

main.cpp
 #include "api.hpp" #include "foo.hpp" #include <list> namespace { void goodConsumer(const Foo& foo) { // do nothing wrong with foo } } int main() { { const auto& api = Api(); goodConsumer(api.getFoo()); std::cout << "*** After good consumer ***\n"; std::cout << api.getFoo() << std::endl; } } 


рдЬрд╛рд╣рд┐рд░ рд╣реИ, рдпрд╣рд╛рдВ рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реИ, рдбреЗрдЯрд╛ рдЕрдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╣реИред

рдирд┐рд╖реНрдХрд░реНрд╖
 *** After good consumer *** INT: 42 STRING: Fish LIST: [0, 1, 2, 3] 

рдФрд░ рдЕрдЧрд░ рдХреЛрдИ рдХреБрдЫ рдмрджрд▓рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддрд╛ рд╣реИ?


main.cpp
 void stupidConsumer(const Foo& foo) { foo.listValue.push_back(100); } 


рд╣рд╛рдВ, рдХреЛрдб рдХреЗрд╡рд▓ рд╕рдВрдХрд▓рди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред

рддреНрд░реБрдЯрд┐
 src/main.cpp: In function 'void {anonymous}::stupidConsumer(const Foo&)': src/main.cpp:16:36: error: passing 'const std::__cxx11::list<int>' as 'this' argument discards qualifiers [-fpermissive] foo.listValue.push_back(100); 


рдХреНрдпрд╛ рдЧрд▓рдд рд╣реЛ рд╕рдХрддрд╛ рд╣реИ?


рдпрд╣ рд╕реА ++ рд╣реИ - рдЕрдкрдиреЗ рдкреИрд░реЛрдВ рдкрд░ рд╢реВрдЯрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рд╣рдерд┐рдпрд╛рд░реЛрдВ рдХреЗ рдПрдХ рд╕рдореГрджреНрдз рд╢рд╕реНрддреНрд░рд╛рдЧрд╛рд░ рдХреЗ рд╕рд╛рде рдПрдХ рднрд╛рд╖рд╛! рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:

main.cpp
 void evilConsumer(const Foo& foo) { const_cast<int&>(foo.intValue) = 7; const_cast<std::string&>(foo.strValue) = "James Bond"; } 


рдЦреИрд░, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╕рдм рдХреБрдЫ:
 *** After evil consumer *** INT: 7 STRING: James Bond LIST: [0, 1, 2, 3] 


рдореИрдВ рдпрд╣ рднреА рдзреНрдпрд╛рди рджреЗрддрд╛ рд╣реВрдВ рдХрд┐ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ const_cast рдмрдЬрд╛рдп reinterpret_cast рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рд╕рдВрдХрд▓рди рддреНрд░реБрдЯрд┐ рд╣реЛ рдЬрд╛рдПрдЧреАред рд▓реЗрдХрд┐рди рд╕реА рдХреА рд╢реИрд▓реА рдореЗрдВ рдХрд╛рд╕реНрдЯ рдЖрдкрдХреЛ рдЗрд╕ рдлрд╝реЛрдХрд╕ рдХреЛ рдХреНрд░реИрдХ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ред

рд╣рд╛рдВ, рдЗрд╕ рддрд░рд╣ рдХреЗ рдХреЛрдб рд╕реЗ рдЕрдкрд░рд┐рднрд╛рд╖рд┐рдд рд╡реНрдпрд╡рд╣рд╛рд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ [C ++ 17 10.1.7.1/4] ред рд╡рд╣ рдЖрдо рддреМрд░ рдкрд░ рд╕рдВрджрд┐рдЧреНрдз рджрд┐рдЦрддрд╛ рд╣реИ, рдЬреЛ рдЕрдЪреНрдЫрд╛ рд╣реИред рд╕рдореАрдХреНрд╖рд╛ рдХреЗ рджреМрд░рд╛рди рдкрдХрдбрд╝рдирд╛ рдЖрд╕рд╛рди рд╣реИ

рдпрд╣ рдмреБрд░рд╛ рд╣реИ рдХрд┐ рджреБрд░реНрднрд╛рд╡рдирд╛рдкреВрд░реНрдг рдХреЛрдб рдЙрдкрднреЛрдХреНрддрд╛ рдореЗрдВ рдХрд╣реАрдВ рднреА рдЫрд┐рдкрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рд╡реИрд╕реЗ рднреА рдХрд╛рдо рдХрд░реЗрдЧрд╛:

main.cpp
 void evilSubConsumer(const std::string& value) { const_cast<std::string&>(value) = "Loki"; } void goodSubConsumer(const std::string& value) { evilSubConsumer(value); } void evilCautiousConsumer(const Foo& foo) { const auto& strValue = foo.strValue; goodSubConsumer(strValue); } 


рдирд┐рд╖реНрдХрд░реНрд╖
 *** After evil but cautious consumer *** INT: 42 STRING: Loki LIST: [0, 1, 2, 3] 


рдЗрд╕ рд╕рдВрджрд░реНрдн рдореЗрдВ C ++ рдХреЗ рдлрд╛рдпрджреЗ рдФрд░ рдиреБрдХрд╕рд╛рди


рдЬреЛ рдЕрдЪреНрдЫрд╛ рд╣реИ:
  • рдЖрдк рдЖрд╕рд╛рдиреА рд╕реЗ рдХреБрдЫ рднреА рдкрдврд╝рдиреЗ рдХреА рдШреЛрд╖рдгрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ
  • рдЗрд╕ рдкреНрд░рддрд┐рдмрдВрдз рдХрд╛ рдЖрдХрд╕реНрдорд┐рдХ рдЙрд▓реНрд▓рдВрдШрди рд╕рдВрдХрд▓рди рдЪрд░рдг рдореЗрдВ рдкрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдирд┐рд░рдВрддрд░ рдФрд░ рдЧреИрд░-рд╕реНрдерд┐рд░ рд╡рд╕реНрддреБрдУрдВ рдореЗрдВ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЗрдВрдЯрд░рдлреЗрд╕ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ
  • рдПрдХ рдХреЛрдб рд╕рдореАрдХреНрд╖рд╛ рдкрд░ рдЧрдВрднреАрд░ рдЙрд▓реНрд▓рдВрдШрди рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ

рдХреНрдпрд╛ рдмреБрд░рд╛ рд╣реИ:
  • рдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рдирд┐рд╖реЗрдз рдХрд╛ рдЬрд╛рдирдмреВрдЭрдХрд░ рдкрд░рд┐рдзрд┐ рд╕рдВрднрд╡ рд╣реИ
  • рдФрд░ рдПрдХ рдкрдВрдХреНрддрд┐ рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд, рдЕрд░реНрдерд╛рддреН рдХреЛрдб рд╕рдореАрдХреНрд╖рд╛ рдкрд░ рдЫреЛрдбрд╝рдирд╛ рдЖрд╕рд╛рди рд╣реИ
  • рдФрд░ рдЕрдкрд░рд┐рднрд╛рд╖рд┐рдд рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдЬрдиреНрдо рджреЗ рд╕рдХрддрд╛ рд╣реИ
  • рдирд┐рд░рдВрддрд░ рдФрд░ рдЧреИрд░-рд╕реНрдерд┐рд░ рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд▓рд┐рдП рд╡рд┐рднрд┐рдиреНрди рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рдХрд╛рд░рдг рд╡рд░реНрдЧ рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЛ рдлреБрд▓рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ


рдЬрд╛рд╡рд╛


рдЬрд╛рд╡рд╛ рдореЗрдВ, рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВ рдЗрд╕реЗ рд╕рдордЭрддрд╛ рд╣реВрдВ, рдереЛрдбрд╝рд╛ рдЕрд▓рдЧ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред final рд░реВрдк рдореЗрдВ рдШреЛрд╖рд┐рдд рдЖрджрд┐рдо рдкреНрд░рдХрд╛рд░ рд╕реА ++ рдореЗрдВ рдЙрд╕реА рддрд░рд╣ рд╕реЗ рд╕реНрдерд┐рд░ рд╣реИрдВред рдЬрд╛рд╡рд╛ рдореЗрдВ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдореВрд▓ рд░реВрдк рд╕реЗ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП final String рд╡рд╣ рд╣реИ рдЬреЛ рд╣рдореЗрдВ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдЪрд╛рд╣рд┐рдПред

рд╕рдВрдЧреНрд░рд╣ рдХреЛ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рдЖрд╡рд░рдгреЛрдВ рдореЗрдВ рд░рдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП java.util.Collections class - unmodifiableList , unmodifiableMap рдЖрджрд┐ рдХреЗ рд╕реНрдерд┐рд░ рддрд░реАрдХреЗ рд╣реИрдВред рдпрд╛рдиреА рдирд┐рд░рдВрддрд░ рдФрд░ рдЧреИрд░-рд╕реНрдерд┐рд░ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╕рдорд╛рди рд╣реИ, рд▓реЗрдХрд┐рди рдЧреИрд░-рд╕реНрдерд┐рд░ рдСрдмреНрдЬреЗрдХреНрдЯ рдЙрдиреНрд╣реЗрдВ рдмрджрд▓рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╕рдордп рдПрдХ рдЕрдкрд╡рд╛рдж рдлреЗрдВрдХрддреЗ рд╣реИрдВред

рдХрд╕реНрдЯрдо рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рдЖрд╡рд░рдг рдмрдирд╛рдиреЗ рд╣реЛрдВрдЧреЗред рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдпрд╣рд╛рдВ рдЬрд╛рд╡рд╛ рдХреЗ рд▓рд┐рдП рдореЗрд░рд╛ рд╡рд┐рдХрд▓реНрдк рд╣реИред

Foo.java
 package foo; import java.util.Collections; import java.util.List; public final class Foo { public final int intValue; public final String strValue; public final List<Integer> listValue; public Foo(final int intValue, final String strValue, final List<Integer> listValue) { this.intValue = intValue; this.strValue = strValue; this.listValue = Collections.unmodifiableList(listValue); } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append("INT: ").append(intValue).append("\n") .append("STRING: ").append(strValue).append("\n") .append("LIST: ").append(listValue.toString()); return sb.toString(); } } 


Api.java
 package api; import foo.Foo; import java.util.Arrays; public final class Api { private final Foo foo = new Foo(42, "Fish", Arrays.asList(0, 1, 2, 3)); public final Foo getFoo() { return foo; } } 


Main.java
 import api.Api; import foo.Foo; public final class Main { private static void goodConsumer(final Foo foo) { // do nothing wrong with foo } public static void main(String[] args) throws Exception { { final Api api = new Api(); goodConsumer(api.getFoo()); System.out.println("*** After good consumer ***"); System.out.println(api.getFoo()); System.out.println(); } } } 


рдирд┐рд╖реНрдХрд░реНрд╖
 *** After good consumer *** INT: 42 STRING: Fish LIST: [0, 1, 2, 3] 


рдЕрд╕рдлрд▓ рдкрд░рд┐рд╡рд░реНрддрди рдХрд╛ рдкреНрд░рдпрд╛рд╕


рдпрджрд┐ рдЖрдк рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдмрджрд▓рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ:

Main.java
 private static void stupidConsumer(final Foo foo) { foo.listValue.add(100); } 


рдпрд╣ рдХреЛрдб рд╕рдВрдХрд▓рд┐рдд рдХрд░реЗрдЧрд╛, рд▓реЗрдХрд┐рди рдПрдХ рдЕрдкрд╡рд╛рдж рд░рдирдЯрд╛рдЗрдо рдкрд░ рдлреЗрдВрдХ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛:

рдЕрдкрд╡рд╛рдж
 Exception in thread "main" java.lang.UnsupportedOperationException at java.base/java.util.Collections$UnmodifiableCollection.add(Collections.java:1056) at Main.stupidConsumer(Main.java:15) at Main.main(Main.java:70) 


рд╕рдлрд▓ рдкреНрд░рдпрд╛рд╕


рдФрд░ рдЕрдЧрд░ рдмреБрд░реЗ рддрд░реАрдХреЗ рд╕реЗ? рдЯрд╛рдЗрдк рд╕реЗ final рдХреНрд╡рд╛рд▓реАрдлрд╛рдпрд░ рдХреЛ рд╣рдЯрд╛рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИред рд▓реЗрдХрд┐рди рдЬрд╛рд╡рд╛ рдореЗрдВ рдПрдХ рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдЪреАрдЬ рд╣реИ - рдкреНрд░рддрд┐рдмрд┐рдВрдмред

Main.java
 import java.lang.reflect.Field; private static void evilConsumer(final Foo foo) throws Exception { final Field intField = Foo.class.getDeclaredField("intValue"); intField.setAccessible(true); intField.set(foo, 7); final Field strField = Foo.class.getDeclaredField("strValue"); strField.setAccessible(true); strField.set(foo, "James Bond"); } 


рдФрд░ рдЗрдореНрдпреБрдирд┐рдЯреА рдЦрддреНрдо рд╣реЛ рдЧрдИ
 *** After evil consumer *** INT: 7 STRING: James Bond LIST: [0, 1, 2, 3] 


рдРрд╕рд╛ рдХреЛрдб C ++ рдореЗрдВ cosnt_cast рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рд╕рдВрджреЗрд╣рд╛рд╕реНрдкрдж рд▓рдЧрддрд╛ рд╣реИ, рдПрдХ рд╕рдореАрдХреНрд╖рд╛ рдкрд░ рдкрдХрдбрд╝рдирд╛ рдФрд░ рднреА рдЖрд╕рд╛рди рд╣реИред рдФрд░ рдпрд╣ рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рдкреНрд░рднрд╛рд╡реЛрдВ рдХреЛ рднреА рдЬрдиреНрдо рджреЗ рд╕рдХрддрд╛ рд╣реИ (рдпрд╛рдиреА, рдХреНрдпрд╛ рдЬрд╛рд╡рд╛ рдореЗрдВ рдпреВрдмреА рд╣реИ ?)ред рдФрд░ рдпрд╣ рдордирдорд╛рдиреЗ рдврдВрдЧ рд╕реЗ рдЧрд╣рд░рд╛рдИ рд╕реЗ рдЫрд┐рдкрд╛ рднреА рд╕рдХрддрд╛ рд╣реИред

рдпреЗ рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рдкреНрд░рднрд╛рд╡ рдЗрд╕ рддрдереНрдп рдХреЗ рдХрд╛рд░рдг рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЬрдм final рд╡рд╕реНрддреБ рдХреЛ рдкреНрд░рддрд┐рдмрд┐рдВрдм рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ hashCode() рд╡рд┐рдзрд┐ рджреНрд╡рд╛рд░рд╛ рд▓реМрдЯрд╛рдпрд╛ рдЧрдпрд╛ рдорд╛рди рд╕рдорд╛рди рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдПрдХ рд╣реА рд╣реИрд╢ рдХреЗ рд╕рд╛рде рдЕрд▓рдЧ-рдЕрд▓рдЧ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╣реИрд╢ рдХреЗ рд╕рд╛рде рд╕рдорд╛рди рдСрдмреНрдЬреЗрдХреНрдЯ рдЦрд░рд╛рдм рд╣реИред

рдЬрд╛рд╡рд╛ рдореЗрдВ рдЗрд╕ рддрд░рд╣ рдХреЗ рд╣реИрдХ рдХрд╛ рдЦрддрд░рд╛ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ ( рдЙрджрд╛рд╣рд░рдг ) рдХреЗ рд▓рд┐рдП рдХреНрдпрд╛ рд╣реИ: рдпрд╣рд╛рдВ рддрд╛рд░ рдкреВрд▓ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдПрдХ рджреВрд╕рд░реЗ рд╕реЗ рдЕрд╕рдВрдмрдВрдзрд┐рдд, рдмрд╕ рдПрдХ рд╣реА рддрд╛рд░ рдкреВрд▓ рдореЗрдВ рд╕рдорд╛рди рдореВрд▓реНрдп рдХрд╛ рд╕рдВрдХреЗрдд рджреЗ рд╕рдХрддреЗ рд╣реИрдВред рдПрдХ рдмрджрд▓ рдЧрдпрд╛ - рдЙрди рд╕рднреА рдХреЛ рдмрджрд▓ рджрд┐рдпрд╛ред

рд▓реЗрдХрд┐рди! JVM рдХреЛ рд╡рд┐рднрд┐рдиреНрди рд╕реБрд░рдХреНрд╖рд╛ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреЗ рд╕рд╛рде рдЪрд▓рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдбрд┐рдлреЙрд▓реНрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ Security Manager рд╕рдХреНрд░рд┐рдп рд╣реЛ рд░рд╣рд╛ рд╣реИ, рдЙрдкрд░реЛрдХреНрдд рд╕рднреА рдЪрд╛рд▓реЛрдВ рдХреЛ рдкрд░рд╛рд╡рд░реНрддрди рдХреЗ рд╕рд╛рде рджрдмрд╛ рджреЗрддрд╛ рд╣реИ:

рдЕрдкрд╡рд╛рдж
 $ java -Djava.security.manager -jar bin/main.jar Exception in thread "main" java.security.AccessControlException: access denied ("java.lang.reflect.ReflectPermission" "suppressAccessChecks") at java.base/java.security.AccessControlContext.checkPermission(AccessControlContext.java:472) at java.base/java.security.AccessController.checkPermission(AccessController.java:895) at java.base/java.lang.SecurityManager.checkPermission(SecurityManager.java:335) at java.base/java.lang.reflect.AccessibleObject.checkPermission(AccessibleObject.java:85) at java.base/java.lang.reflect.Field.setAccessible(Field.java:169) at Main.evilConsumer(Main.java:20) at Main.main(Main.java:71) 


рдЗрд╕ рд╕рдВрджрд░реНрдн рдореЗрдВ рдЬрд╛рд╡рд╛ рдХреЗ рдлрд╛рдпрджреЗ рдФрд░ рдиреБрдХрд╕рд╛рди


рдЬреЛ рдЕрдЪреНрдЫрд╛ рд╣реИ:
  • рдПрдХ final рдХреАрд╡рд░реНрдб рд╣реИ рдЬреЛ рдХрд┐рд╕реА рднреА рддрд░рд╣ рдбреЗрдЯрд╛ рдкрд░рд┐рд╡рд░реНрддрди рдХреЛ рд╕реАрдорд┐рдд рдХрд░рддрд╛ рд╣реИ
  • рд╕рдВрдЧреНрд░рд╣ рдХреЛ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рдореЗрдВ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╡рд┐рдзрд┐рдпрд╛рдБ рд╣реИрдВ
  • рдХреЛрдб рдХреА рд╕рдореАрдХреНрд╖рд╛ рд╕реЗ рд╕рдЪреЗрдд рдкреНрд░рддрд┐рд░рдХреНрд╖рд╛ рдЙрд▓реНрд▓рдВрдШрди рдХрд╛ рдЖрд╕рд╛рдиреА рд╕реЗ рдкрддрд╛ рд▓рдЧрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ
  • JVM рд╕реБрд░рдХреНрд╖рд╛ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рд╣реИрдВ

рдХреНрдпрд╛ рдмреБрд░рд╛ рд╣реИ:
  • рдПрдХ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╡рд╕реНрддреБ рдХреЛ рдмрджрд▓рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХреЗрд╡рд▓ рд░рдирдЯрд╛рдЗрдо рдкрд░ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛
  • рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╡рд░реНрдЧ рдХреА рд╡рд╕реНрддреБ рдХреЛ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд╕реНрд╡рдпрдВ рдЙрдЪрд┐рдд рдЖрд╡рд░рдг рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛
  • рдЙрдЪрд┐рдд рд╕реБрд░рдХреНрд╖рд╛ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреЗ рдЕрднрд╛рд╡ рдореЗрдВ, рдХрд┐рд╕реА рднреА рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рдбреЗрдЯрд╛ рдХреЛ рдмрджрд▓рдирд╛ рд╕рдВрднрд╡ рд╣реИ
  • рдЗрд╕ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЗ рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рдкрд░рд┐рдгрд╛рдо рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ (рд╣рд╛рд▓рд╛рдВрдХрд┐ рд╢рд╛рдпрдж рдпрд╣ рдЕрдЪреНрдЫрд╛ рд╣реИ - рд▓рдЧрднрдЧ рдХреЛрдИ рднреА рдРрд╕рд╛ рдирд╣реАрдВ рдХрд░реЗрдЧрд╛)


рдЕрдЬрдЧрд░


рдЦреИрд░, рдЙрд╕рдХреЗ рдмрд╛рдж рдореИрдВ рдмрд╕ рдЬрд┐рдЬреНрдЮрд╛рд╕рд╛ рдХреА рд▓рд╣рд░реЛрдВ рдХреЗ рд╕рд╛рде рдмрд╣ рдЧрдпрд╛ред рдЗрд╕ рддрд░рд╣ рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХреИрд╕реЗ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдкрд╛рдпрдерди рдореЗрдВ? рдФрд░ рдХреНрдпрд╛ рд╡реЗ рдмрд┐рд▓реНрдХреБрд▓ рддрдп рд╣реИрдВ? рджрд░рдЕрд╕рд▓, рдЕрдЬрдЧрд░ рдореЗрдВ рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ рдХреЛрдИ рдмрд╛рдзрд╛ рдирд╣реАрдВ рд╣реИ, рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдРрд╕реЗ рдХреЛрдИ рдХреАрд╡рд░реНрдб рдирд╣реАрдВ рд╣реИрдВред

foo.py
 class Foo(): def __init__(self, int_value, str_value, list_value): self.int_value = int_value self.str_value = str_value self.list_value = list_value def __str__(self): return 'INT: ' + str(self.int_value) + '\n' + \ 'STRING: ' + self.str_value + '\n' + \ 'LIST: ' + str(self.list_value) 


api.py
 from foo import Foo class Api(): def __init__(self): self.__foo = Foo(42, 'Fish', [0, 1, 2, 3]) def get_foo(self): return self.__foo 


main.py
 from api import Api def good_consumer(foo): pass def evil_consumer(foo): foo.int_value = 7 foo.str_value = 'James Bond' def main(): api = Api() good_consumer(api.get_foo()) print("*** After good consumer ***") print(api.get_foo()) print() api = Api() evil_consumer(api.get_foo()) print("*** After evil consumer ***") print(api.get_foo()) print() if __name__ == '__main__': main() 


рдирд┐рд╖реНрдХрд░реНрд╖
 *** After good consumer *** INT: 42 STRING: Fish LIST: [0, 1, 2, 3] *** After evil consumer *** INT: 7 STRING: James Bond LIST: [0, 1, 2, 3] 


рдпрд╛рдиреА рдХреЛрдИ рдЪрд╛рд▓ рдХреА рдЬрд░реВрд░рдд рдирд╣реАрдВ рд╣реИ, рдЗрд╕реЗ рд▓реЗ рд▓реЛ рдФрд░ рдХрд┐рд╕реА рднреА рд╡рд╕реНрддреБ рдХреЗ рдХреНрд╖реЗрддреНрд░ рдХреЛ рдмрджрд▓ рджреЗрдВред

рд╕рдЬреНрдЬрди рдХрд╛ рд╕рдордЭреМрддрд╛


рдЕрдЬрдЧрд░ рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкреНрд░рдерд╛ рд╕реНрд╡реАрдХрд╛рд░ рдХреА рдЬрд╛рддреА рд╣реИ:
  • рдХрд╕реНрдЯрдо рдлрд╝реАрд▓реНрдб рдФрд░ рд╡рд┐рдзрд┐рдпрд╛рдБ рдЬрд┐рдирдХреЗ рдирд╛рдо рдПрдХрд▓ рдЕрдВрдбрд░рд╕реНрдХреЛрд░ рд╕реЗ рд╢реБрд░реВ рд╣реЛрддреЗ рд╣реИрдВ, рд╕рдВрд░рдХреНрд╖рд┐рдд (C ++ рдФрд░ рдЬрд╛рд╡рд╛ рдореЗрдВ рд╕рдВрд░рдХреНрд╖рд┐рдд ) рдлрд╝реАрд▓реНрдб рдФрд░ рд╡рд┐рдзрд┐рдпрд╛рдБ рд╣реИрдВ
  • рдХрд╕реНрдЯрдо рдлрд╝реАрд▓реНрдб рдФрд░ рджреЛ рдЕрдВрдбрд░рд╕реНрдХреЛрд░ рд╕реЗ рд╢реБрд░реВ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рдирд╛рдореЛрдВ рдХреЗ рддрд░реАрдХреЗ рдирд┐рдЬреА рдлрд╝реАрд▓реНрдб рдФрд░ рд╡рд┐рдзрд┐рдпрд╛рдБ рд╣реИрдВ

рднрд╛рд╖рд╛ "рдирд┐рдЬреА" рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд▓рд┐рдП рднреА рдкреНрд░рдмрдВрдз рдХрд░рддреА рд╣реИред рдПрдХ рдмрд╣реБрдд рднреЛрд▓реА рд╕рдЬрд╛рд╡рдЯ, рд╕реА ++ рдХреЗ рд╕рд╛рде рдХреЛрдИ рддреБрд▓рдирд╛ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдЕрдирдЬрд╛рдиреЗ (рдпрд╛ рднреЛрд▓реА) рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдЕрдирджреЗрдЦрд╛ рдХрд░рдиреЗ (рд▓реЗрдХрд┐рди рдкрдХрдбрд╝рдиреЗ рдирд╣реАрдВ) рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИред

рдХреЛрдб
 class Foo(): def __init__(self, int_value): self.__int_value = int_value def int_value(self): return self.__int_value def evil_consumer(foo): foo.__int_value = 7 


рдирд┐рд╖реНрдХрд░реНрд╖
 *** After evil consumer *** INT: 42 


рдФрд░ рдЬрд╛рдирдмреВрдЭрдХрд░ рдЧрд▓рддреА рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд╕ рдХреБрдЫ рд╡рд░реНрдг рдЬреЛрдбрд╝реЗрдВред

рдХреЛрдб
 def evil_consumer(foo): foo._Foo__int_value = 7 


рдирд┐рд╖реНрдХрд░реНрд╖
 *** After evil consumer *** INT: 7 


рдПрдХ рдФрд░ рд╡рд┐рдХрд▓реНрдк


рдореБрдЭреЗ Oz N Tiram рджреНрд╡рд╛рд░рд╛ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рд╕рдорд╛рдзрд╛рди рдкрд╕рдВрдж рдЖрдпрд╛ред рдпрд╣ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рд╕рдЬреНрдЬрд╛рдХрд╛рд░ рд╣реИ рдХрд┐ рдЬрдм рдХреЗрд╡рд▓ рдкрдврд╝рдиреЗ рдХреЗ рдХреНрд╖реЗрддреНрд░ рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рдЬрд╛рддреА рд╣реИ рддреЛ рдПрдХ рдЕрдкрд╡рд╛рдж рд╣реЛрддрд╛ рд╣реИред рдпрд╣ рд╕рд╣рдордд рджрд╛рдпрд░реЗ рд╕реЗ рдереЛрдбрд╝рд╛ рд╕рд╛ рдкрд░реЗ рд╣реИ ("рддрд░реАрдХреЛрдВ рдФрд░ рдЗрдВрдЯрд░рдлреЗрд╕ рдХрд╛ рдПрдХ рдЧреБрдЪреНрдЫрд╛ рди рдмрдирд╛рдПрдВ"), рд▓реЗрдХрд┐рди, рдлрд┐рд░ рд╕реЗ, рдореБрдЭреЗ рдпрд╣ рдкрд╕рдВрдж рдЖрдпрд╛ред

foo.py
 from read_only_properties import read_only_properties @read_only_properties('int_value', 'str_value', 'list_value') class Foo(): def __init__(self, int_value, str_value, list_value): self.int_value = int_value self.str_value = str_value self.list_value = list_value def __str__(self): return 'INT: ' + str(self.int_value) + '\n' + \ 'STRING: ' + self.str_value + '\n' + \ 'LIST: ' + str(self.list_value) 


main.py
 def evil_consumer(foo): foo.int_value = 7 foo.str_value = 'James Bond' 


рдирд┐рд╖реНрдХрд░реНрд╖
 Traceback (most recent call last): File "src/main.py", line 35, in <module> main() File "src/main.py", line 28, in main evil_consumer(api.get_foo()) File "src/main.py", line 9, in evil_consumer foo.int_value = 7 File "/home/Tmp/python/src/read_only_properties.py", line 15, in __setattr__ raise AttributeError("Can't touch {}".format(name)) AttributeError: Can't touch int_value 


рд▓реЗрдХрд┐рди рдпрд╣ рд░рд╛рдордмрд╛рдг рдирд╣реАрдВ рд╣реИред рд▓реЗрдХрд┐рди рдХрдо рд╕реЗ рдХрдо рд╕рдВрдмрдВрдзрд┐рдд рдХреЛрдб рд╕рдВрджрд┐рдЧреНрдз рд▓рдЧ рд░рд╣рд╛ рд╣реИред

main.py
 def evil_consumer(foo): foo.__dict__['int_value'] = 7 foo.__dict__['str_value'] = 'James Bond' 


рдирд┐рд╖реНрдХрд░реНрд╖
 *** After evil consumer *** INT: 7 STRING: James Bond LIST: [0, 1, 2, 3] 


рдЗрд╕ рд╕рдВрджрд░реНрдн рдореЗрдВ рдкрд╛рдпрдерди рдХреЗ рдлрд╛рдпрджреЗ рдФрд░ рдиреБрдХрд╕рд╛рди


рдХреНрдпрд╛ рдЕрдЬрдЧрд░ рдмрд╣реБрдд рдмреБрд░рд╛ рд▓рдЧрддрд╛ рд╣реИ? рдирд╣реАрдВ, рдпрд╣ рднрд╛рд╖рд╛ рдХрд╛ рд╕рд┐рд░реНрдл рдПрдХ рдФрд░ рджрд░реНрд╢рди рд╣реИред рдЖрдорддреМрд░ рдкрд░ рдпрд╣ рд╡рд╛рдХреНрдпрд╛рдВрд╢ " рд╣рдо рд╕рднреА рд╕рд╣рдорддрд┐ рд╡рдпрд╕реНрдХ рдпрд╣рд╛рдБ рд╣реИрдВ " рджреНрд╡рд╛рд░рд╛ рд╡реНрдпрдХреНрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ ( рд╣рдо рд╕рднреА рдпрд╣рд╛рдБ рд╡рдпрд╕реНрдХ рд╕рд╣рдорддрд┐ рджреЗ рд░рд╣реЗ рд╣реИрдВ )ред рдпрд╛рдиреА рдпрд╣ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдХреЛрдИ рднреА рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╕реНрд╡реАрдХреГрдд рдорд╛рдирджрдВрдбреЛрдВ рд╕реЗ рд╡рд┐рдЪрд▓рд┐рдд рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рдЕрд╡рдзрд╛рд░рдгрд╛ рдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдЬреАрд╡рди рдХрд╛ рдЕрдзрд┐рдХрд╛рд░ рд╣реИред

рдЬреЛ рдЕрдЪреНрдЫрд╛ рд╣реИ:
  • рдпрд╣ рдЦреБрд▓реЗ рддреМрд░ рдкрд░ рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреЛ рдПрдХреНрд╕реЗрд╕ рдЕрдзрд┐рдХрд╛рд░реЛрдВ рдХреА рдирд┐рдЧрд░рд╛рдиреА рдХрд░рдиреА рдЪрд╛рд╣рд┐рдП, рди рдХрд┐ рдХрдВрдкрд╛рдЗрд▓рд░ рдпрд╛ рджреБрднрд╛рд╖рд┐рдпрд╛ рдХреА
  • рд╕реБрд░рдХреНрд╖рд┐рдд рдФрд░ рдирд┐рдЬреА рдХреНрд╖реЗрддреНрд░реЛрдВ рдФрд░ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЖрдо рддреМрд░ рдкрд░ рд╕реНрд╡реАрдХреГрдд рдирд╛рдордХрд░рдг рд╕рдореНрдореЗрд▓рди рд╣реИ
  • рдХреЛрдб рдХреА рд╕рдореАрдХреНрд╖рд╛ рдкрд░ рдХреБрдЫ рдПрдХреНрд╕реЗрд╕ рдЙрд▓реНрд▓рдВрдШрдиреЛрдВ рдХрд╛ рдЖрд╕рд╛рдиреА рд╕реЗ рдкрддрд╛ рд▓рдЧрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ

рдХреНрдпрд╛ рдмреБрд░рд╛ рд╣реИ:
  • рднрд╛рд╖рд╛ рдХреЗ рд╕реНрддрд░ рдкрд░ рд╡рд░реНрдЧ рдХреЗ рдХреНрд╖реЗрддреНрд░реЛрдВ рддрдХ рдкрд╣реБрдВрдЪ рдХреЛ рдкреНрд░рддрд┐рдмрдВрдзрд┐рдд рдХрд░рдирд╛ рдЕрд╕рдВрднрд╡ рд╣реИ
  • рд╕рдм рдХреБрдЫ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреА рд╕рджреНрднрд╛рд╡рдирд╛ рдФрд░ рдИрдорд╛рдирджрд╛рд░реА рдкрд░ рдЯрд┐рдХреА рд╣реБрдИ рд╣реИ
  • рддреНрд░реБрдЯрд┐рдпрд╛рдВ рдХреЗрд╡рд▓ рд░рдирдЯрд╛рдЗрдо рдкрд░ рд╣реЛрддреА рд╣реИрдВ


рдЬрд╛рдУ


рдПрдХ рдФрд░ рднрд╛рд╖рд╛ рдЬрд┐рд╕реЗ рдореИрдВ рд╕рдордп-рд╕рдордп рдкрд░ рдорд╣рд╕реВрд╕ рдХрд░рддрд╛ рд╣реВрдВ (рдЬреНрдпрд╛рджрд╛рддрд░ рд╕рд┐рд░реНрдл рд▓реЗрдЦ рдкрдврд╝ рд░рд╣рд╛ рд╣реВрдВ), рд╣рд╛рд▓рд╛рдВрдХрд┐ рдореИрдВрдиреЗ рдЕрднреА рддрдХ рдЗрд╕ рдкрд░ рд╡рд╛рдгрд┐рдЬреНрдпрд┐рдХ рдХреЛрдб рдХреА рдПрдХ рдкрдВрдХреНрддрд┐ рдирд╣реАрдВ рд▓рд┐рдЦреА рд╣реИред const рдХреАрд╡рд░реНрдб рдореВрд▓ рд░реВрдк рд╕реЗ рд╣реИ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рддрд╛рд░ рдФрд░ рдкреВрд░реНрдгрд╛рдВрдХ рдорд╛рди рдЬрд┐рд╕реЗ рдЬреНрдЮрд╛рдд рд╕рдордп рдкрд░ рд╕рдВрдХрд▓рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдпрд╛рдиреА C ++ рд╕реЗ constexpr ) constexpr рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рд╕рдВрд░рдЪрдирд╛ рдХреНрд╖реЗрддреНрд░ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗред рдпрд╛рдиреА рдпрджрд┐ рдЦреЗрддреЛрдВ рдХреЛ рдЦреБрд▓рд╛ рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рдЕрдЬрдЧрд░ рдХреА рддрд░рд╣ рдирд┐рдХрд▓рддрд╛ рд╣реИ - рдЬреЛ рдЖрдк рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдЙрд╕реЗ рдмрджрд▓реЗрдВред рдиреАрд░рд╕ред рдореИрдВрдиреЗ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЛрдб рднреА рдирд╣реАрдВ рджрд┐рдпрд╛ред

рдЦреИрд░, рдЦреЗрддреЛрдВ рдХреЛ рдирд┐рдЬреА рд╣реЛрдиреЗ рджреЗрдВ, рдФрд░ рдЦреБрд▓реЗ рдореВрд▓реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдХреЙрд▓ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЙрдирдХреЗ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рджреЗрдВред рдХреНрдпрд╛ рдореБрдЭреЗ рдЧреЛ рдореЗрдВ рдЬрд▓рд╛рдК рд▓рдХрдбрд╝реА рдорд┐рд▓ рд╕рдХрддреА рд╣реИ? рдмреЗрд╢рдХ, рдпрд╣рд╛рдБ рдкреНрд░рддрд┐рдмрд┐рдВрдм рднреА рд╣реИред

foo.go
 package foo import "fmt" type Foo struct { intValue int strValue string listValue []int } func (foo *Foo) IntValue() int { return foo.intValue; } func (foo *Foo) StrValue() string { return foo.strValue; } func (foo *Foo) ListValue() []int { return foo.listValue; } func (foo *Foo) String() string { result := fmt.Sprintf("INT: %d\nSTRING: %s\nLIST: [", foo.intValue, foo.strValue) for i, num := range foo.listValue { if i > 0 { result += ", " } result += fmt.Sprintf("%d", num) } result += "]" return result } func New(i int, s string, l []int) Foo { return Foo{intValue: i, strValue: s, listValue: l} } 


api.go
 package api import "foo" type Api struct { foo foo.Foo } func (api *Api) GetFoo() *foo.Foo { return &api.foo } func New() Api { api := Api{} api.foo = foo.New(42, "Fish", []int{0, 1, 2, 3}) return api } 


main.go
 package main import ( "api" "foo" "fmt" "reflect" "unsafe" ) func goodConsumer(foo *foo.Foo) { // do nothing wrong with foo } func evilConsumer(foo *foo.Foo) { reflectValue := reflect.Indirect(reflect.ValueOf(foo)) member := reflectValue.FieldByName("intValue") intPointer := unsafe.Pointer(member.UnsafeAddr()) realIntPointer := (*int)(intPointer) *realIntPointer = 7 member = reflectValue.FieldByName("strValue") strPointer := unsafe.Pointer(member.UnsafeAddr()) realStrPointer := (*string)(strPointer) *realStrPointer = "James Bond" } func main() { apiInstance := api.New() goodConsumer(apiInstance.GetFoo()) fmt.Println("*** After good consumer ***") fmt.Println(apiInstance.GetFoo().String()) fmt.Println() apiInstance = api.New() evilConsumer(apiInstance.GetFoo()) fmt.Println("*** After evil consumer ***") fmt.Println(apiInstance.GetFoo().String()) } 


рдирд┐рд╖реНрдХрд░реНрд╖
 *** After good consumer *** INT: 42 STRING: Fish LIST: [0, 1, 2, 3] *** After evil consumer *** INT: 7 STRING: James Bond LIST: [0, 1, 2, 3] 


рд╡реИрд╕реЗ, рдЧреЛ рдореЗрдВ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╣реИрдВ, рдЬреИрд╕реЗ рдЬрд╛рд╡рд╛ рдореЗрдВред рд╕реНрд▓рд╛рдЗрд╕ рдФрд░ рдирдХреНрд╢реЗ рдкрд░рд╕реНрдкрд░ рд╣реИрдВ, рдФрд░ рдЬрд╛рд╡рд╛ рдХреЗ рд╡рд┐рдкрд░реАрдд, рдЙрдиреНрд╣реЗрдВ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рднрд╛рд╖рд╛ рдХреЗ рдореВрд▓ рдореЗрдВ рдХреЛрдИ рд░рд╛рд╕реНрддрд╛ рдирд╣реАрдВ рд╣реИред рдХреЗрд╡рд▓ рдХреЛрдб рдЬрдирд░реЗрд╢рди (рдпрджрд┐ рдореИрдВ рдЧрд▓рдд рд╣реВрдВ рддреЛ рд╕рд╣реА)ред рдпрд╛рдиреА рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЕрдЧрд░ рд╕рдм рдХреБрдЫ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЧрдВрджреЗ рдЪрд╛рд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рди рдХрд░реЗрдВ, рдмрд╕ рд╕реНрд▓рд╛рдЗрд╕ рдХреЛ рд╡рд┐рдзрд┐ рд╕реЗ рд▓реМрдЯрд╛рдПрдВ - рдпрд╣ рдЯреБрдХрдбрд╝рд╛ рд╣рдореЗрд╢рд╛ рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ

рдЧреЛрдлрд░ рд╕рдореБрджрд╛рдп рдореЗрдВ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЕрднрд╛рд╡ рд╣реИ , рд▓реЗрдХрд┐рди рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдЧреЛ 1.x рдореЗрдВ рдХреЛрдИ рднреА рдирд╣реАрдВ рд╣реЛрдЧрд╛ред

рдЗрд╕ рд╕рдВрджрд░реНрдн рдореЗрдВ рдЧреЛ рдХреЗ рдлрд╛рдпрджреЗ рдФрд░ рдиреБрдХрд╕рд╛рди


рдЧреЛ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЗ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рдмрджрд▓рдиреЗ рдкрд░ рд░реЛрдХ рд▓рдЧрд╛рдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛рдУрдВ рдкрд░ рдореЗрд░реЗ рдЕрдиреБрднрд╡рд╣реАрди рджреГрд╖реНрдЯрд┐рдХреЛрдг рдореЗрдВ, рдпрд╣ рдЬрд╛рд╡рд╛ рдФрд░ рдкрд╛рдпрдерди рдХреЗ рдмреАрдЪ рдХрд╣реАрдВ рд╣реИ, рдмрд╛рдж рдХреЗ рдХрд░реАрдмред рдЙрд╕реА рд╕рдордп, рдЧреЛ рдирд╣реАрдВ (рдореИрдВ рдирд╣реАрдВ рдорд┐рд▓рд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдореИрдВ рджреЗрдЦ рд░рд╣рд╛ рдерд╛) рд╡рдпрд╕реНрдХреЛрдВ рдХреЗ рдкрд╛рдпрдерди рд╕рд┐рджреНрдзрд╛рдВрддред рд▓реЗрдХрд┐рди рд╡рд╣рд╛рдБ рд╣реИ: рдПрдХ рдкреИрдХреЗрдЬ рдХреЗ рдЕрдВрджрд░ рд╕рдм рдХреБрдЫ рдХреЗ рд▓рд┐рдП рд╕рдм рдХреБрдЫ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣реЛрддрд╛ рд╣реИ, рдХреЗрд╡рд▓ рд╕реНрдерд┐рд░рд╛рдВрдХ рд╕реЗ рдЕрд╢рд┐рд╖реНрдЯрддрд╛ рдмрдиреА рд╣реБрдИ рд╣реИ, рдЕрдиреБрдкрдпреЛрдЧреА рд╕рдВрдЧреНрд░рд╣ рдХреА рдЕрдиреБрдкрд╕реНрдерд┐рддрд┐ рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ред рдпрд╛рдиреА рдЕрдЧрд░ рдбреЗрд╡рд▓рдкрд░ рдХреБрдЫ рдбреЗрдЯрд╛ рдкрдврд╝ рд╕рдХрддрд╛ рд╣реИ, рддреЛ рдЙрдЪреНрдЪ рд╕рдВрднрд╛рд╡рдирд╛ рдХреЗ рд╕рд╛рде рд╡рд╣ рд╡рд╣рд╛рдВ рдХреБрдЫ рд▓рд┐рдЦ рд╕рдХрддрд╛ рд╣реИред рдЬреЛ, рдЕрдЬрдЧрд░ рдХреЗ рд░реВрдк рдореЗрдВ, рд╕рдВрдХрд▓рдХ рд╕реЗ рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдЬрд┐рдореНрдореЗрджрд╛рд░реА рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддрд╛ рд╣реИред

рдЬреЛ рдЕрдЪреНрдЫрд╛ рд╣реИ:
  • рд╕рдВрдХрд▓рди рдХреЗ рджреМрд░рд╛рди рд╕рднреА рдкрд╣реБрдВрдЪ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реЛрддреА рд╣реИрдВ
  • рд╕рдореАрдХреНрд╖рд╛ рдореЗрдВ рдкреНрд░рддрд┐рдмрд┐рдВрдм рдЖрдзрд╛рд░рд┐рдд рдЧрдВрджреА рдЪрд╛рд▓ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рджрд┐рдЦрд╛рдИ рджреЗ рд░рд╣реА рд╣реИ

рдХреНрдпрд╛ рдмреБрд░рд╛ рд╣реИ:
  • "рдХреЗрд╡рд▓ рдкрдврд╝рдиреЗ рд╡рд╛рд▓реЗ рдбреЗрдЯрд╛рд╕реЗрдЯ" рдХреА рдХреЛрдИ рдЕрд╡рдзрд╛рд░рдгрд╛ рдирд╣реАрдВ рд╣реИ
  • рдкреИрдХреЗрдЬ рдХреЗ рднреАрддрд░ рд╕рдВрд░рдЪрдирд╛ рдХреНрд╖реЗрддреНрд░реЛрдВ рддрдХ рдкрд╣реБрдВрдЪ рдХреЛ рдкреНрд░рддрд┐рдмрдВрдзрд┐рдд рдХрд░рдирд╛ рдЕрд╕рдВрднрд╡ рд╣реИ
  • рдкреИрдХреЗрдЬ рдХреЗ рдмрд╛рд╣рд░ рдХреЗ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рд╕реЗ рдЦреЗрддреЛрдВ рдХреЛ рдмрдЪрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЧреЗрдЯрд░реНрд╕ рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛
  • рд╕рднреА рд╕рдВрджрд░реНрдн рд╕рдВрдЧреНрд░рд╣ рдкрд░рд╕реНрдкрд░ рд╣реИрдВ
  • рдкреНрд░рддрд┐рдмрд┐рдВрдм рдХреА рд╕рд╣рд╛рдпрддрд╛ рд╕реЗ рдЖрдк рдирд┐рдЬреА рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рднреА рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВ


Erlang


рдпрд╣ рдкреНрд░рддрд┐рдпреЛрдЧрд┐рддрд╛ рд╕реЗ рдмрд╛рд╣рд░ рд╣реИред рдлрд┐рд░ рднреА, рдПрд░реНрд▓рд╛рдВрдЧ рдПрдХ рднрд╛рд╖рд╛ рд╣реИ рдЬреЛ рдЙрдкрд░реЛрдХреНрдд рдЪрд╛рд░реЛрдВ рд╕реЗ рдмрд╣реБрдд рдЕрд▓рдЧ рдкреНрд░рддрд┐рдорд╛рди рд╣реИред рдПрдХ рдмрд╛рд░ рдЬрдм рдореИрдВрдиреЗ рдмрдбрд╝реА рджрд┐рд▓рдЪрд╕реНрдкреА рд╕реЗ рдЗрд╕рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд┐рдпрд╛, рддреЛ рдореБрдЭреЗ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЦреБрдж рдХреЛ рдПрдХ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╢реИрд▓реА рдореЗрдВ рд╕реЛрдЪрдирд╛ рдкрд╕рдВрдж рдЖрдпрд╛ред рд▓реЗрдХрд┐рди, рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдореБрдЭреЗ рдЗрди рдХреМрд╢рд▓реЛрдВ рдХрд╛ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдирд╣реАрдВ рдорд┐рд▓рд╛ред

рддреЛ, рдЗрд╕ рднрд╛рд╖рд╛ рдореЗрдВ рдПрдХ рдЪрд░ рдХрд╛ рдорд╛рди рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рд╕реМрдВрдкрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдФрд░ рдЬрдм рдлрд╝рдВрдХреНрд╢рди рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╕рднреА рддрд░реНрдХ рдореВрд▓реНрдп рджреНрд╡рд╛рд░рд╛ рдкрд╛рд░рд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ, рдЕрд░реНрдерд╛рддред рдЙрдирдХреА рдПрдХ рдкреНрд░рддрд┐ рдмрдирд╛рдИ рдЧрдИ рд╣реИ (рд▓реЗрдХрд┐рди рдкреВрдВрдЫ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХрд╛ рдПрдХ рдЕрдиреБрдХреВрд▓рди рд╣реИ)ред

foo.erl
 -module(foo). -export([new/3, print/1]). new(IntValue, StrValue, ListValue) -> {foo, IntValue, StrValue, ListValue}. print(Foo) -> case Foo of {foo, IntValue, StrValue, ListValue} -> io:format("INT: ~w~nSTRING: ~s~nLIST: ~w~n", [IntValue, StrValue, ListValue]); _ -> throw({error, "Not a foo term"}) end. 


api.erl
 -module(api). -export([new/0, get_foo/1]). new() -> {api, foo:new(42, "Fish", [0, 1, 2, 3])}. get_foo(Api) -> case Api of {api, Foo} -> Foo; _ -> throw({error, "Not an api term"}) end. 


main.erl
 -module(main). -export([start/0]). start() -> ApiForGoodConsumer = api:new(), good_consumer(api:get_foo(ApiForGoodConsumer)), io:format("*** After good consumer ***~n"), foo:print(api:get_foo(ApiForGoodConsumer)), io:format("~n"), ApiForEvilConsumer = api:new(), evil_consumer(api:get_foo(ApiForEvilConsumer)), io:format("*** After evil consumer ***~n"), foo:print(api:get_foo(ApiForEvilConsumer)), init:stop(). good_consumer(_) -> done. evil_consumer(Foo) -> _ = setelement(1, Foo, 7), _ = setelement(2, Foo, "James Bond"). 


рдирд┐рд╖реНрдХрд░реНрд╖
 *** After good consumer *** INT: 42 STRING: Fish LIST: [0,1,2,3] *** After evil consumer *** INT: 42 STRING: Fish LIST: [0,1,2,3] 


рдмреЗрд╢рдХ, рдЖрдк рд╣рд░ рдЫреАрдВрдХ рдХреЗ рд▓рд┐рдП рдкреНрд░рддрд┐рдпрд╛рдВ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕рд▓рд┐рдП рдЦреБрдж рдХреЛ рдЕрдиреНрдп рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рдбреЗрдЯрд╛ рднреНрд░рд╖реНрдЯрд╛рдЪрд╛рд░ рд╕реЗ рдмрдЪрд╛ рд╕рдХрддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдПрдХ рднрд╛рд╖рд╛ рд╣реИ (рдФрд░ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдПрдХ рдирд╣реАрдВ) рдЬрд╣рд╛рдВ рдпрд╣ рдмрд╕ рджреВрд╕рд░реЗ рддрд░реАрдХреЗ рд╕реЗ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ!

рдЗрд╕ рд╕рдВрджрд░реНрдн рдореЗрдВ рдПрд░рд▓рд╛рдВрдЧ рдХреЗ рдлрд╛рдпрджреЗ рдФрд░ рдиреБрдХрд╕рд╛рди


рдЬреЛ рдЕрдЪреНрдЫрд╛ рд╣реИ:
  • рдбреЗрдЯрд╛ рдореЗрдВ рдмрд┐рд▓реНрдХреБрд▓ рдмрджрд▓рд╛рд╡ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ

рдХреНрдпрд╛ рдмреБрд░рд╛ рд╣реИ:
  • рд╣рд░ рдЬрдЧрд╣ рдирдХрд▓, рдирдХрд▓


рдирд┐рд╖реНрдХрд░реНрд╖ рдФрд░ рдирд┐рд╖реНрдХрд░реНрд╖ рдХреЗ рдмрдЬрд╛рдп


рдФрд░ рдЗрд╕рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдХреНрдпрд╛ рд╣реИ? рдЦреИрд░, рдЗрд╕ рддрдереНрдп рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдХрд┐ рдореИрдВрдиреЗ рдХреБрдЫ рд╕рдордп рдкрд╣рд▓реЗ рдкрдврд╝реА рдЧрдИ рдХреБрдЫ рдкреБрд╕реНрддрдХреЛрдВ рд╕реЗ рдзреВрд▓ рдЙрдбрд╝рд╛ рджреА, рдореИрдВрдиреЗ рдЕрдкрдиреА рдЙрдВрдЧрд▓рд┐рдпреЛрдВ рдХреЛ рдмрдврд╝рд╛рдпрд╛, 5 рдЕрд▓рдЧ-рдЕрд▓рдЧ рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рдПрдХ рдмреЗрдХрд╛рд░ рдХрд╛рд░реНрдпрдХреНрд░рдо рд▓рд┐рдЦрд╛ рдФрд░ рдПрдлрдПрдХреНрдпреВ рдЦрд░реЛрдВрдЪ рдХрд┐рдпрд╛?

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдореИрдВрдиреЗ рдпрд╣ рд╕реЛрдЪрдирд╛ рдмрдВрдж рдХрд░ рджрд┐рдпрд╛ рдХрд┐ рд╕реА ++ рдПрдХ рд╕рдХреНрд░рд┐рдп рдореВрд░реНрдЦ рдХреЗ рдЦрд┐рд▓рд╛рдл рд╕реБрд░рдХреНрд╖рд╛ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рд╕рдмрд╕реЗ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рднрд╛рд╖рд╛ рд╣реИред рдЕрдкрдиреЗ рд╕рднреА рд▓рдЪреАрд▓реЗрдкрди рдФрд░ рд╕рдореГрджреНрдз рд╡рд╛рдХреНрдп рд░рдЪрдирд╛ рдХреЗ рдмрд╛рд╡рдЬреВрджред рдЕрдм рдореИрдВ рдпрд╣ рд╕реЛрдЪрдиреЗ рдореЗрдВ рдЗрдЪреНрдЫреБрдХ рд╣реВрдВ рдХрд┐ рдЗрд╕ рд╕рдВрдмрдВрдз рдореЗрдВ рдЬрд╛рд╡рд╛ рдЕрдзрд┐рдХ рд╕реБрд░рдХреНрд╖рд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдмрд╣реБрдд рд╣реА рдореВрд▓ рдирд┐рд╖реНрдХрд░реНрд╖ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдкрдиреЗ рд▓рд┐рдП рдореИрдВ рдЗрд╕реЗ рдмрд╣реБрдд рдЙрдкрдпреЛрдЧреА рдорд╛рдирддрд╛ рд╣реВрдВред

рджреВрд╕рд░реЗ, рдореИрдВрдиреЗ рдЕрдЪрд╛рдирдХ рдЕрдкрдиреЗ рд▓рд┐рдП рдпрд╣ рд╡рд┐рдЪрд╛рд░ рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ рдХрд┐ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛рдУрдВ рдХреЛ рдореЛрдЯреЗ рддреМрд░ рдкрд░ рдЙрди рд▓реЛрдЧреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬреЛ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдФрд░ рд╢рдмреНрджрд╛рд░реНрде рдХреЗ рд╕реНрддрд░ рдкрд░ рдХреБрдЫ рдбреЗрдЯрд╛ рддрдХ рдкрд╣реБрдВрдЪ рдХреЛ рдкреНрд░рддрд┐рдмрдВрдзрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдЗрди рдЪрд┐рдВрддрд╛рдУрдВ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рднреА рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред ред рддрджрдиреБрд╕рд╛рд░, рдкреНрд░рд╡реЗрд╢ рд╕реАрдорд╛, рд╕рд░реНрд╡реЛрддреНрддрдо рдЕрднреНрдпрд╛рд╕, рдЯреАрдо рд╡рд┐рдХрд╛рд╕ рдкреНрд░рддрд┐рднрд╛рдЧрд┐рдпреЛрдВ (рддрдХрдиреАрдХреА рдФрд░ рд╡реНрдпрдХреНрддрд┐рдЧрдд рджреЛрдиреЛрдВ) рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдВ рдХрд┐рд╕реА рднреА рддрд░рд╣ рд╕реЗ рд░реБрдЪрд┐ рдХреА рдЪрдпрдирд┐рдд рднрд╛рд╖рд╛ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рднрд┐рдиреНрди рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред рдореБрдЭреЗ рдЗрд╕ рд╡рд┐рд╖рдп рдкрд░ рдкрдврд╝рдирд╛ рдЕрдЪреНрдЫрд╛ рд▓рдЧреЗрдЧрд╛ред

рддреАрд╕рд░реА рдмрд╛рдд: рдбреЗрдЯрд╛ рдХреЛ рд▓рд┐рдЦрдиреЗ рд╕реЗ рдмрдЪрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рднрд╛рд╖рд╛ рдЪрд╛рд╣реЗ рдХрд┐рддрдиреА рднреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд▓реЗ, рд▓реЗрдХрд┐рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЪрд╛рд╣реЗрдВ рддреЛ рдпрд╣ рд▓рдЧрднрдЧ рд╣рдореЗрд╢рд╛ рдХрд░ рд╕рдХрддрд╛ рд╣реИ ("рд▓рдЧрднрдЧ" рдПрд░реНрд▓рд╛рдВрдЧ рдХреЗ рдХрд╛рд░рдг)ред рдФрд░ рдЕрдЧрд░ рдЖрдк рдЦреБрдж рдХреЛ рдореБрдЦреНрдп рдзрд╛рд░рд╛ рдХреА рднрд╛рд╖рд╛рдУрдВ рддрдХ рд╕реАрдорд┐рдд рд░рдЦрддреЗ рд╣реИрдВ - рддреЛ рдпрд╣ рд╣рдореЗрд╢рд╛ рдЖрд╕рд╛рди рд╣реЛрддрд╛ рд╣реИред рдФрд░ рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рдЗрди рд╕рднреА const рдФрд░ final рдореЗрдВ рд╕рд┐рдлрд╛рд░рд┐рд╢реЛрдВ рд╕реЗ рдЕрдзрд┐рдХ рдХреБрдЫ рдирд╣реАрдВ рд╣реИ, рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЗ рд╕рд╣реА рдЙрдкрдпреЛрдЧ рдХреЗ рдирд┐рд░реНрджреЗрд╢ рд╣реИрдВред рд╕рднреА рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рдпрд╣ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рдЕрднреА рднреА рдЕрдкрдиреЗ рд╢рд╕реНрддреНрд░рд╛рдЧрд╛рд░ рдореЗрдВ рдРрд╕реЗ рдЙрдкрдХрд░рдг рд░рдЦрдирд╛ рдкрд╕рдВрдж рдХрд░рддрд╛ рд╣реВрдВред

-, : () , , тАФ . , , const , - ( ), , , ( ) . рдпрд╛рдиреАрдореБрдЭреЗ рдЕрдкрдиреЗ рд╕рд╛рдерд┐рдпреЛрдВ рдкрд░ рднрд░реЛрд╕рд╛ рд╣реИ ред

рдирд╣реАрдВ, рдореИрдВ рд▓рдВрдмреЗ рд╕рдордп рд╕реЗ рдЬрд╛рдирддрд╛ рд╣реВрдВ рдХрд┐ рдЖрдзреБрдирд┐рдХ рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рд╡рд┐рдХрд╛рд╕ 99.99% рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдЯреАрдо рд╡рд░реНрдХ рд╣реИред рд▓реЗрдХрд┐рди рдореИрдВ рднрд╛рдЧреНрдпрд╢рд╛рд▓реА рдерд╛, рдореЗрд░реЗ рд╕рднреА рд╕рд╛рдереА "рд╡рдпрд╕реНрдХ, рдЬрд┐рдореНрдореЗрджрд╛рд░" рд▓реЛрдЧ рдереЗред рдореЗрд░реЗ рд▓рд┐рдП, рдпрд╣ рд╣рдореЗрд╢рд╛ рдХрд┐рд╕реА рди рдХрд┐рд╕реА рддрд░рд╣ рд░рд╣рд╛ рд╣реИ, рдФрд░ рдпрд╣ рдЗрд╕ рдмрд╛рдд рдХреЗ рд▓рд┐рдП рд▓рд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рд╕рднреА рдЯреАрдо рдХреЗ рд╕рджрд╕реНрдп рд╕реНрдерд╛рдкрд┐рдд рдирд┐рдпрдореЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд░реЗрдВред рдореБрдЭреЗ рдЗрд╕ рдмрд╛рдд рдХрд╛ рдПрд╣рд╕рд╛рд╕ рд╣реИ рдХрд┐ рд╣рдо рд▓рдЧрд╛рддрд╛рд░ рдПрдХ рджреВрд╕рд░реЗ рдкрд░ рднрд░реЛрд╕рд╛ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╕рдореНрдорд╛рди рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╢рд╛рдВрдд рдФрд░ рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реИред

рдкреБрдирд╢реНрдЪ


рдпрджрд┐ рдХреЛрдИ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рдХреЛрдб рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддрд╛ рд╣реИ, рддреЛ рдЖрдк рдЙрдиреНрд╣реЗрдВ рдпрд╣рд╛рдВ рд▓реЗ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ ред

Source: https://habr.com/ru/post/hi447478/


All Articles