äžè¬çã«ç§ã¯C ++ããã°ã©ãã§ãã ãŸãããã¯èµ·ãã£ãã ç§ã®ãã£ãªã¢ã§æžããåçšã³ãŒãã®å€§éšåã¯C ++ã§ãã ç§ã¯ãããèšèªã«å¯Ÿããå人çãªçµéšã®ãã®ãããªåŒ·ãåããããŸã奜ãã§ã¯ãããŸãããå¥ã®èšèªã§äœããæžãæ©äŒãéããªãããã«ããŠããŸãã ãããŠãç§ã®çŸåšã®éçšäž»ã¯çªç¶ãã®ãããªæ©äŒãæäŸããŸãããç§ã¯ãJavaã§æãäºçŽ°ãªãŠãŒãã£ãªãã£ã§ã¯ãªããã®ãäœãããšãçŽæããŸããã å®è£
èšèªã®éžæã¯æŽå²çãªçç±ã§è¡ãããŸããããç§ã¯æ°ã«ããŸããã§ããã Javaã ããJavaãç§ã«ã¯ããŸã銎æã¿ããªã-è¯ãã
ãšããããè«ççã«é¢é£ããç¹å®ã®ããŒã¿ã®ã»ãããäœæããŠç¹å®ã®ã³ã³ã·ã¥ãŒããŒã«è»¢éãããšãããããªãåçŽãªã¿ã¹ã¯ããããŸããã ããã€ãã®ã³ã³ã·ã¥ãŒããŒãååšããå¯èœæ§ããããã«ãã»ã«åã®ååã«ããã°ãéä¿¡ã³ãŒãïŒãããã¥ãŒãµãŒïŒã¯ããœãŒã¹ããŒã¿ã§äœãã§ãããœãŒã¹ããŒã¿ã§äœãã§ããããç¥ããŸããã ãããã補é æ¥è
ã¯åæ¶è²»è
ãåãããŒã¿ãåãåãå¿
èŠããããŸãã ã³ããŒãäœã£ãŠãããããããŸããã§ããã ããã¯ãæ¶è²»è
ã«éä¿¡ãããããŒã¿ãå€æŽããæ©äŒãäœããã®æ¹æ³ã§å¥ªãå¿
èŠãããããšãæå³ããŸãã
ãã®æãããJavaã§ã®ç§ã®äžæ
£ãããæããããŸããã C ++ãšæ¯èŒããŠèšèªæ©èœãæ¬ ããŠããŸããã ã¯ãã
final
ããŒã¯ãŒãããããŸããã
final
final Object
ã¯
const Object*
ã§ã¯ãªããC ++ã®
Object* const
ã«äŒŒãŠããŸãã ã€ãŸã
final List<String>
ã«ã¯ãããšãã°è¡ãè¿œå ã§ããŸãã ããã¯C ++ããžãã¹ã§ãããã€ã€ãŒãºã®èšŒèšã«åŸã£ãŠ
const
ã©ãã«ã§ãé
眮ããããšãããã ãã§ãïŒ èª°ãäœãå€ããŸããã ã ããïŒ ãŸããããã§ããªãã ç§ã¯äœæã«
ãã®ãŠãŒãã£ãªãã£ãå®è¡ãã代ããã«ãããã«ã€ããŠå°ãèããŸããããããç§ããã£ãããšã§ãã
C ++
ã¿ã¹ã¯èªäœãæãåºãããŠãã ããïŒ
- ããŒã¿ã»ããã1åäœæããŸãã
- äžå¿
èŠã«ã³ããŒããªãã§ãã ããã
- æ¶è²»è
ããã®ããŒã¿ãå€æŽã§ããªãããã«ããŸãã
- ã³ãŒããæå°åãã€ãŸã äžè¬ã«ãã»ãã®æ°ãæã§ãå¿
èŠãªããŒã¿ã»ããããšã«å€æ°ã®ã¡ãœãããšã€ã³ã¿ãŒãã§ã€ã¹ãäœæããªãã§ãã ããã
ãã«ãã¹ã¬ãããäŸå€çãªæå³ã§ã®ã»ãã¥ãªãã£ãªã©ã®æªåããæ¡ä»¶ã¯ãããŸããã æãåçŽãªã±ãŒã¹ãèããŠã¿ãŸãããã ç§ãæã䜿ãæ
£ããèšèªã䜿çšããŠãããè¡ãæ¹æ³ã¯æ¬¡ã®ãšããã§ãã
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; } }
æããã«ãããã§ã¯ãã¹ãŠãæ£åžžã§ãããããŒã¿ã¯å€æŽãããŠããŸããã
ãããŠèª°ããäœããå€ããããšãããïŒ
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);
äœãããããã®ã§ããããïŒ
ããã¯C ++ã§ã-èªåã®è¶³ã§æ®åœ±ããããã®è±å¯ãªæŠåšãåããèšèªã§ãïŒ äŸïŒ
main.cpp void evilConsumer(const Foo& foo) { const_cast<int&>(foo.intValue) = 7; const_cast<std::string&>(foo.strValue) = "James Bond"; }
ãŸããå®éã«ã¯ãã¹ãŠïŒ ãŸãããã®å Žåã«
const_cast
代ããã«
const_cast
ã䜿çšãããšãã³ã³ãã€ã«ãšã©ãŒãçºçããããšã«æ³šæããŠãã ããã ãã ããCã¹ã¿ã€ã«ã®ãã£ã¹ãã䜿çšãããšããã®çŠç¹ãçµãããšãã§ããŸãã
ã¯ãããã®ãããªã³ãŒãã¯æªå®çŸ©ã®åäœ
[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); }
ãã®ã³ã³ããã¹ãã§ã®C ++ã®é·æãšçæ
ã©ã¡ããè¯ãã§ããïŒ
- äœã§ãç°¡åã«èªã¿åãã¢ã¯ã»ã¹ã宣èšã§ããŸã
- ãã®å¶éã®å¶çºçãªéåã¯ãã³ã³ãã€ã«æ®µéã§æ€åºãããŸãã å®æ°ãªããžã§ã¯ããšéå®æ°ãªããžã§ã¯ãã¯ç°ãªãã€ã³ã¿ãŒãã§ãŒã¹ãæã€ããšãã§ããŸã
- ã³ãŒãã¬ãã¥ãŒã§æèçãªéåãæ€åºã§ãã
æªãç¹ïŒ
- å€æŽã®çŠæ¢ãæèçã«åé¿ããããšãå¯èœã§ã
- 1è¡ã§å®è¡ãããŸãã ã³ãŒãã¬ãã¥ãŒã§ã¹ããããããã
- æªå®çŸ©ã®åäœã«ã€ãªããå¯èœæ§ããããŸã
- å®æ°ãªããžã§ã¯ããšéå®æ°ãªããžã§ã¯ãã«ç°ãªãã€ã³ã¿ãŒãã§ãŒã¹ãå®è£
ããå¿
èŠããããããã¯ã©ã¹å®çŸ©ãæ¡åŒµã§ããŸã
Java
Javaã§ã¯ãç§ãç解ããŠããããã«ããããã«ç°ãªãã¢ãããŒãã䜿çšãããŸãã
final
ãšããŠå®£èšãããããªããã£ãåã¯ãC ++ãšåãæå³ã§å®æ°ã§ãã Javaã®
final String
ã¯åºæ¬çã«äžå€ã§ããããããã®å Žåã«å¿
èŠãªã®ã¯
final String
çãª
final String
ã§ãã
ã³ã¬ã¯ã·ã§ã³ã¯äžå€ã®ã©ãããŒã«é
眮ã§ããŸãããã®ããã«ã¯ã
java.util.Collections
ã¯ã©ã¹ã®éçã¡ãœãã
unmodifiableList
ã
unmodifiableMap
ãªã©ããããŸãã ã€ãŸã å®æ°ãªããžã§ã¯ããšéå®æ°ãªããžã§ã¯ãã®ã€ã³ã¿ãŒãã§ãŒã¹ã¯åãã§ãããéå®æ°ãªããžã§ã¯ããå€æŽããããšãããšäŸå€ãã¹ããŒãããŸãã
ãŠãŒã¶ãŒã¿ã€ãã«é¢ããŠã¯ããŠãŒã¶ãŒèªèº«ãäžå€ã®ã©ãããŒãäœæããå¿
èŠããããŸãã äžè¬ã«ãJavaã®ãªãã·ã§ã³ã¯æ¬¡ã®ãšããã§ãã
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) {
倱æããå€æŽã®è©Šã¿
ããšãã°ãäœããå€æŽããããšããå ŽåïŒ
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
修食åãåé€ããæ¹æ³ã¯ãããŸããã ããããJavaã«ã¯ãã£ãšåŒ·åãªãã®ããããŸã-ãªãã¬ã¯ã·ã§ã³ã§ãã
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"); }
ãããŠå
ç«ã«å¯Ÿãã ãã®ãããªã³ãŒãã¯ãC ++ã®
cosnt_cast
ããã
cosnt_cast
èŠãããããã¬ãã¥ãŒããã£ããããã®ãããã«ç°¡åã§ãã ãããŠãããã¯ãŸã
äºæž¬äžå¯èœãªå¹æã«ã€ãªããå¯èœ
æ§ããããŸã ïŒã€ãŸããJavaã«ã¯
UBããããŸããïŒïŒã ãŸããä»»æã«æ·±ãé ãããšãã§ããŸãã
ãããã®äºæž¬äžå¯èœãªåœ±é¿ã¯ããªãã¬ã¯ã·ã§ã³ã䜿çšããŠ
final
ãªããžã§ã¯ããå€æŽããããšãã«ã
hashCode()
ã¡ãœããã«ãã£ãŠè¿ãããå€ãåããŸãŸã§ããå¯ââèœæ§ãããããã§ãã åãããã·ã¥ãæã€ç°ãªããªããžã§ã¯ãã¯åé¡ã«ãªããŸããããç°ãªãããã·ã¥ãæã€åããªããžã§ã¯ãã¯æªãã§ãã
ãã®ãããªJavaã§ã®æååå°çšã®ãããã³ã°ã®å±éºæ§ã¯äœã§ããïŒ
äŸ ïŒãããã§ã®æååã¯ããŒã«ã«ä¿åã§ããäºãã«ç¡é¢ä¿ã§ãåãæååã ããããŒã«å
ã®åãå€ã瀺ãããšãã§ããŸãã å€æŽããããã®-ããããã¹ãŠãå€æŽããŸããã
ãããïŒ
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)
ãã®ã³ã³ããã¹ãã§ã®Javaã®é·æãšçæ
ã©ã¡ããè¯ãã§ããïŒ
- ããŒã¿ã®å€æŽãäœããã®åœ¢ã§å¶éãã
final
ããŒã¯ãŒãããããŸã - ã³ã¬ã¯ã·ã§ã³ãäžå€ã«ããã©ã€ãã©ãªã¡ãœããããããŸã
- æèçãªå
ç«éåã¯ã³ãŒãã¬ãã¥ãŒã§ç°¡åã«æ€åºãããŸã
- JVMã»ãã¥ãªãã£èšå®ããã
æªãç¹ïŒ
- äžå€ãªããžã§ã¯ããå€æŽããããšããè©Šã¿ã¯ãå®è¡æã«ã®ã¿çºçããŸã
- ç¹å®ã®ã¯ã©ã¹ã®ãªããžã§ã¯ããäžå€ã«ããã«ã¯ãé©åãªã©ãããŒãèªåã§äœæããå¿
èŠããããŸã
- é©åãªã»ãã¥ãªãã£èšå®ããªãå Žåãäžå€ããŒã¿ãå€æŽããããšãå¯èœã§ã
- ãã®ã¢ã¯ã·ã§ã³ã¯äºæž¬äžå¯èœãªçµæãââããããå¯èœæ§ããããŸãïŒãã ããããã¯è¯ãããšãããããŸãã-ã»ãšãã©èª°ããããè¡ããŸããïŒ
Python
ãŸãããã®åŸãç§ã¯åã«å¥œå¥å¿ã®æ³¢ã«æµãããŸããã ãã®ãããªã¿ã¹ã¯ã¯ãããšãã°Pythonã§ã©ã®ããã«è§£æ±ºãããŸããïŒ ãããŠã圌ãã¯ãŸã£ãã決å®ãããŠããŸããïŒ å®éãPythonã«ã¯ããã®ãããªããŒã¯ãŒãããªããŠããååãšããŠäžå€ã¯ãããŸããã
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()
ã€ãŸã ããªãã¯ã¯å¿
èŠãããŸããããããåãããªããžã§ã¯ãã®ãã£ãŒã«ããå€æŽããŸãã
玳士åå®
Pythonã§ã¯ã次ã®
ãã©ã¯ãã£ã¹ãåãå
¥ããããŸãã
- ååã1ã€ã®ã¢ã³ããŒã¹ã³ã¢ã§å§ãŸãã«ã¹ã¿ã ãã£ãŒã«ããšã¡ãœããã¯ä¿è·ãããŠããŸãïŒC ++ããã³Javaã§ä¿è·ãããŠããŸãïŒãã£ãŒã«ããšã¡ãœãã
- 2ã€ã®ã¢ã³ããŒã¹ã³ã¢ã§å§ãŸãååã®ã«ã¹ã¿ã ãã£ãŒã«ããšã¡ãœããã¯ãã©ã€ããŒããã£ãŒã«ããšã¡ãœããã§ã
ãã®èšèªã¯ãããã©ã€ããŒãããã£ãŒã«ãã®
ãã³ã°ãªã³ã°ãè¡ããŸãã éåžžã«çŽ æŽãªè£
食ã§ã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
ãããŠãæå³çã«ééããç¯ãã«ã¯ãããã€ãã®æåãè¿œå ããã ãã§ãã
ã³ãŒã def evil_consumer(foo): foo._Foo__int_value = 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'
ãã®ã³ã³ããã¹ãã§ã®Pythonã®é·æãšçæ
Pythonã¯éåžžã«æªãããã«èŠããŸããïŒ ããããããã¯èšèªã®ãã1ã€ã®å²åŠã§ãã éåžžãããã¯ã
ããã§ã¯ãã¹ãŠåæãã倧人ã§ã ããšãããã¬ãŒãºã§è¡šãããŸãïŒ
ããã§ã¯ãã¹ãŠåæãã倧人ã§ã ïŒã ã€ãŸã æ¿èªãããæšæºããæ確ã«éžè±ããè
ã¯ããªããšæ³å®ãããŠããŸãã ã³ã³ã»ããã¯å®ãã§ã¯ãããŸããããçããæš©å©ããããŸãã
ã©ã¡ããè¯ãã§ããïŒ
- ããã°ã©ããŒã¯ã³ã³ãã€ã©ãŒãŸãã¯ã€ã³ã¿ãŒããªã¿ãŒã§ã¯ãªããã¢ã¯ã»ã¹æš©ãç£èŠããå¿
èŠããããšå
¬ã«å®£èšãããŠããŸã
- å®å
šã§ãã©ã€ããŒããªãã£ãŒã«ããšã¡ãœããã«ã¯äžè¬çã«åãå
¥ããããŠããåœåèŠåããããŸã
- äžéšã®ã¢ã¯ã»ã¹éåã¯ã³ãŒãã¬ãã¥ãŒã§ç°¡åã«æ€åºãããŸã
æªãç¹ïŒ
- èšèªã¬ãã«ã§ã¯ãã¯ã©ã¹ã®ãã£ãŒã«ããžã®ã¢ã¯ã»ã¹ãå¶éããããšã¯äžå¯èœã§ã
- ãã¹ãŠã¯éçºè
ã®åæãšèª å®ãã«ã®ã¿ããã£ãŠããŸã
- ãšã©ãŒã¯å®è¡æã«ã®ã¿çºçããŸã
è¡ã
ç§ãå®æçã«æããŠããå¥ã®èšèªïŒäž»ã«èšäºãèªãã§ããã ãã§ãïŒã§ããããŸã åçšã³ãŒããæžããŠããŸããã
const
ããŒã¯ãŒãã¯åºæ¬çã«ããã«ãããŸãããã³ã³ãã€ã«æã«æ¢ç¥ã®æååãšæŽæ°å€ïŒã€ãŸããC ++ã®
constexpr
ïŒã®ã¿ãå®æ°ã«ãªããŸãã ããããæ§é ãã£ãŒã«ãã¯ã§ããŸããã ã€ãŸã ãã£ãŒã«ãããªãŒãã³ã§ãããšå®£èšãããŠããå ŽåãPythonã®ããã«ãªããŸã-åžæãã人ãå€æŽããŸãã é¢çœããªãã ã³ãŒãã®äŸãæããŸããã
ããŠããã£ãŒã«ãããã©ã€ããŒãã«ããŠãå€ãopenã¡ãœããã®åŒã³åºãã§ååŸã§ããããã«ããŸãã Goã§fireãå
¥æã§ããŸããïŒ ãã¡ãããããã«ãåå°ããããŸãã
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) {
ãšããã§ãGoã®æååã¯Javaã®ããã«äžå€ã§ãã ã¹ã©ã€ã¹ãšãããã¯å¯å€ã§ãããJavaãšã¯ç°ãªããèšèªã®ã³ã¢ã«ã¯ããããäžå€ã«ããæ¹æ³ã¯ãããŸããã ã³ãŒãçæã®ã¿ïŒç§ãééã£ãŠããã°æ£ããïŒã ã€ãŸã ãã¹ãŠãæ£ããè¡ããããšããŠããããŒãã£ããªãã¯ã䜿çšããã«ãã¡ãœããããã¹ã©ã€ã¹ãè¿ãã ãã§ãããã®ã¹ã©ã€ã¹ã¯ãã€ã§ãå€æŽã§ããŸãã
gopherã³ãã¥ããã£ã«ã¯æãã
ã«äžå€ã®åããããŸããããGo 1.xã«ã¯ç¢ºãã«ååšããŸããã
ãã®ã³ã³ããã¹ãã§ã®Goã®é·æãšçæ
Goæ§é äœã®ãã£ãŒã«ãã®å€æŽãçŠæ¢ããå¯èœæ§ã«ã€ããŠã®ç§ã®çµéšã®æµ
ãèŠè§£ã§ã¯ãJavaãšPythonã®éã®ã©ããã«ãããåŸè
ã«è¿ããã®ã§ãã åæã«ãGoã¯Pythonã®å€§äººã®ååãæºãããŠããŸããïŒç§ã¯æ¢ããŠããŸããããäŒããŸããã§ããïŒã ãã ãã1ã€ã®ããã±ãŒãžå
ã§ã¯ãã¹ãŠããã¹ãŠã«ã¢ã¯ã»ã¹ã§ããå®æ°ããã¯åºæ¬çãªãã®ã®ã¿ãæ®ããå€æŽäžå¯èœãªã³ã¬ã¯ã·ã§ã³ãååšããªãããšã瀺ããŸãã ã€ãŸã éçºè
ãäœããã®ããŒã¿ãèªã¿åããå Žåãé«ã確çã§äœããæžã蟌ãããšãã§ããŸãã ããã¯ãPythonã®å Žåã®ããã«ãã³ã³ãã€ã©ãŒãã人ã«ã»ãšãã©ã®è²¬ä»»ãäŒããŸãã
ã©ã¡ããè¯ãã§ããïŒ
- ãã¹ãŠã®ã¢ã¯ã»ã¹ãšã©ãŒã¯ã³ã³ãã€ã«äžã«çºçããŸã
- åå°ããŒã¹ã®ããŒãã£ããªãã¯ã¯ã¬ãã¥ãŒã§ã¯ã£ãããšèŠãã
æªãç¹ïŒ
- ãèªã¿åãå°çšããŒã¿ã»ãããã®æŠå¿µã¯åçŽã§ã¯ãããŸãã
- ããã±ãŒãžå
ã®æ§é ãã£ãŒã«ããžã®ã¢ã¯ã»ã¹ãå¶éããããšã¯äžå¯èœã§ã
- ããã±ãŒãžå€ã®å€æŽãããã£ãŒã«ããä¿è·ããã«ã¯ãã²ãã¿ãŒãäœæããå¿
èŠããããŸã
- ãã¹ãŠã®åç
§ã³ã¬ã¯ã·ã§ã³ã¯å€æŽå¯èœã§ã
- ãªãã¬ã¯ã·ã§ã³ã®å©ããåããŠããã©ã€ããŒããã£ãŒã«ããå€æŽããããšãã§ããŸã
ã¢ãŒã©ã³
ããã¯ç«¶äºã®å¯Ÿè±¡å€ã§ãã ããã§ããErlangã¯äžèšã®4ã€ãšã¯éåžžã«ç°ãªããã©ãã€ã ãæã€èšèªã§ãã èå³ãæã£ãŠå匷ããããèªåãæ©èœçãªã¹ã¿ã€ã«ã§èããããã®ãæ¬åœã«å¥œãã§ããã ããããæ®å¿µãªããããããã®ã¹ãã«ã®å®çšçãªå¿çšã¯èŠã€ãããŸããã§ããã
ãã®ããããã®èšèªã§ã¯ãå€æ°ã®å€ã¯äžåºŠããå²ãåœãŠãããšãã§ããŸããã ãããŠãé¢æ°ãåŒã³åºããããšããã¹ãŠã®åŒæ°ã¯å€ã§æž¡ãããŸãã ãããã®ã³ããŒãäœæãããŸãïŒãã ããæ«å°Ÿååž°ã®æé©åããããŸãïŒã
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").
ãã¡ããããããã¿ããšã«ã³ããŒãäœæã§ãããããä»ã®èšèªã®ããŒã¿ç Žæãã身ãå®ãããšãã§ããŸãã ããããä»ã®æ¹æ³ã§ãããåçŽã«è¡ãããšã®ã§ããªãèšèªããããŸãïŒç¢ºãã«ããã§ã¯ãããŸããïŒã
ãã®ã³ã³ããã¹ãã§ã®Erlangã®é·æãšçæ
ã©ã¡ããè¯ãã§ããïŒ
- ããŒã¿ã¯ãŸã£ããå€æŽã§ããŸãã
æªãç¹ïŒ
- ã³ããŒãã©ãã§ãã³ããŒ
çµè«ãšçµè«ã®ä»£ããã«
ãããŠãçµæã¯äœã§ããïŒ ãŸããæèªãã æ¬ããã»ãããå¹ãé£ã°ãããšããäºå®ã«å ããŠãç§ã¯æã䌞ã°ãã5ã€ã®ç°ãªãèšèªã§åœ¹ã«ç«ããªãããã°ã©ã ãæžããFACãå·ã€ããŸãããïŒ
ãŸããC ++ãã¢ã¯ãã£ããªãã«ã«å¯Ÿããä¿è·ã®èŠ³ç¹ããæãä¿¡é Œã§ããèšèªã§ãããšèããã®ããããŸããã ãã¹ãŠã®æè»æ§ãšè±å¯ãªæ§æã«ããããããã ä»ãç§ã¯ãã®ç¹ã§Javaãããå€ãã®ä¿è·ãæäŸãããšèããåŸåããããŸãã ããã¯éåžžã«ç¬åµçãªçµè«ã§ã¯ãããŸããããç§ã«ãšã£ãŠã¯éåžžã«äŸ¿å©ã§ãã
第äºã«ãããã°ã©ãã³ã°èšèªã¯ãæ§æãšã»ãã³ãã£ã¯ã¹ã®ã¬ãã«ã§ç¹å®ã®ããŒã¿ãžã®ã¢ã¯ã»ã¹ãå¶éããããšããèšèªãšããŠãŒã¶ãŒã«ãããã®æžå¿µã移ãããšããªãèšèªãšã«å€§ãŸãã«åããããšãã§ãããšããèããçªç¶æãã€ããŸããã ã ãããã£ãŠããšã³ããªã®ãããå€ããã¹ããã©ã¯ãã£ã¹ãããŒã éçºåå è
ïŒæè¡çããã³å人çïŒã®èŠä»¶ã¯ãéžæããé¢å¿ã®ããèšèªã«ãã£ãŠäœããã®åœ¢ã§ç°ãªãå¿
èŠããããŸãã ãã®ããŒãã«ã€ããŠèªã¿ããã§ãã
3çªç®ïŒèšèªãã©ã®ããã«ããŒã¿ãæžã蟌ã¿ããä¿è·ããããšããŠãããŠãŒã¶ãŒã¯å¿
èŠã«å¿ããŠã»ãŒãã€ã§ããããè¡ãããšãã§ããŸãïŒErlangã®ãããã§ãã»ãŒãïŒã ãããŠãããªããäž»æµã®èšèªã«ãšããããŠãããªããããã¯ãã€ãç°¡åã§ãã ãããŠããããã®
const
ãš
final
ã¯ãã¹ãŠãæšå¥šäºé
ãã€ãŸãã€ã³ã¿ãŒãã§ãŒã¹ãæ£ãã䜿çšããããã®æ瀺ã«ãããŸããã ãã¹ãŠã®èšèªããããæã£ãŠããããã§ã¯ãããŸããããç§ã¯ãŸã ãã®ãããªããŒã«ãèªåã®æŠåšã«æã€ããšã奜ã¿ãŸãã
ãããŠç¬¬4ã«ãæãéèŠãªããšã§ããïŒäž»æµã®ïŒèšèªã¯éçºè
ãåä»ãªããšãè¡ãããšã劚ããããšãã§ããªãããããã®éçºè
ãç¶æããå¯äžã®ããšã¯åœŒèªèº«ã®è¯èã§ãã
ãããŠconst
ãã³ãŒããå
¥ãããšããååïŒããã³ç§ã®å°æ¥ã®èªåïŒã«äœããçŠæ¢ããã®ã§ã¯ãªãã圌ãïŒãããŠç§ïŒã圌ãã«åŸããšä¿¡ããŠæ瀺ãæ®ããŠããããšãããããŸããã€ãŸã
ç§ã¯ååãä¿¡é ŒããŠããŸããããããç§ã¯é·ãéãææ°ã®ãœãããŠã§ã¢éçºãããŒã äœæ¥ã®99.99ïŒ
ã§ããããšãç¥ã£ãŠããŸããããããç§ã¯å¹žéã§ãããç§ã®ååã¯ãã¹ãŠã倧人ã責任è
ãã§ãããç§ã«ãšã£ãŠã¯ãåžžã«ããã§ããããã¹ãŠã®ããŒã ã¡ã³ããŒã確ç«ãããã«ãŒã«ãé å®ããããšã¯åœç¶ã®ããšã§ããç§ãã¡ã絶ãããäºããä¿¡é Œãå°æ¬ããŠãããšããèªèã«è³ããŸã§ã®éã®ãã¯é·ããã®ã§ããããå·éã§å®å
šã§ããPS
誰ãã䜿çšãããã³ãŒãäŸã«èå³ããããªããããªãã¯ããããããã§åãããšãã§ããŸãã