Java King: Позвольте мне рассказать вам, что такое настоящая инкапсуляция!

Java

Первый король Яванской империи официально взошел на престол, и поздравить его пришли сотни официальных лиц.

Министр А сказал: «Поздравляю Его Величество с восхождением на престол. Чтобы привлечь больше программистов в нашу страну, я предлагаю как можно скорее улучшить возможности ООП нашего языка Java, включая инкапсуляцию, наследование и полиморфизм».

Король сказал: "По порядку, давайте сначала поговорим об инкапсуляции. Теперь мы можем поместить данные и методы в класс, а затем мы можем попытаться скрыть информацию и ограничить доступ к ним. Я слышал, что сейчас много людей. Если вы используете C++, можете ли вы чему-нибудь на нем научиться?»

Министр Б очень любил C++ и сказал: "Ваше Величество, в C++ есть такие ключевые слова, как public, private и protected, которые можно использовать для изменения свойств и методов. Мы можем использовать их напрямую".

public class Person{    private String name;    private int age;    public String getName(){        return name;    }    public int getAge(){        return age;    }}скопировать код

«Как хорошо!» Король зааплодировал, но закатил глаза и вдруг подумал о Python, который появился несколькими годами ранее, и спросил: «Как Python справляется с проблемой инкапсуляции?»

Министр А прибыл из королевства Питонов, чтобы «повернуться на его сторону». Извиняясь перед родиной, он действительно хотел привнести немного синтаксиса Python в Java. Услышав этот вопрос короля, он быстро сказал: «Питон относительно прост. иметь дело с двумя знаками подчеркивания для обозначения частных свойств и методов».

class Person:    def __init__(self, name):        self.name = name        # 私有属性        self.__age = 10     # 私有方法    def __secret(self):        return  self.__agep = Person("andy")#可以访问print(p.name)   #私有属性,无法访问print(p.__age)  #私有方法,无法访问print(p.__secret())  скопировать код

Но король сказал: «Ну, этот метод довольно прост. Его можно осуществить с помощью подчеркивания. Это очень просто. Можем ли мы сделать то же самое?»

Второй министр немного посмотрел на этот скриптовый язык свысока и быстро сказал: «Абсолютно нет, Ваше Величество ничего не знает, этот Python, даже если он подчеркнут, является лишь «псевдо-приватным» атрибутом и методом».

«Что такое псевдо-частное?»

«Это все еще способ получить доступ к ним снаружи!»

#用这种方法,依然可以访问伪私有属性和方法print(p._Person__age)       # 10print(p._Person__secret())  # 10скопировать код

"Что это за частная собственность и метод? Это совсем не чисто", - продолжал исправлять министр Б.

Король сказал: «Ладно, не будем его учить. А как насчет JavaScript? Как он реализовал инкапсуляцию?»

Министры КНДР и Китая переглянулись, JavaScript? Что за чертовщина? Почему вы не слышали об этом?

(Примечание производителя кода: JavaScript появился позже, чем Java, и этот король Java, по оценкам, прошел.)

скрыть класс

Министр А увидел, что его идея «не увенчалась успехом», и выбрал другой подход: «Ваше Величество, в Python есть модульный механизм, который может объединять несколько классов в единое целое. Должны ли мы сделать то же самое в Java?»

Король посмотрел на министра А и сделал выговор: «Не учите Python для всего! У нас также должно быть что-то уникальное. Для того, чтобы организовать занятия, мы можем использовать пакеты. Пакет соответствует каталогу в файловой системе, и там может быть несколько под ним. файл класса. Если класс не изменен публичным доступом, к нему могут получить доступ только классы в том же пакете, а классы в других пакетах недоступны. Хороший ли это дизайн?!»

Король был очень горд.

В одном пакете есть три класса A, B и C. Только класс A может быть доступен внешним пакетам и может действовать как внешний «интерфейс» этого пакета (примечание: не интерфейс Java), B и C видны только в уровень пакета Класс эквивалентен внутренней реализации пакета, и внешний мир не может быть новым, предотвращая неправильное использование внешним миром.

Пока гарантируется, что A не изменится, это не повлияет на использование внешнего мира, а B и C могут измениться так, как они хотят!

класс друзей

Министр А осторожно спросил: «Что, если я хочу предоставить доступ к foo.cmd только классу B в foo.core, не позволяя другим пакетам получить доступ к классу B?»

«Как может быть такое «извращенное» требование?» Все министры КНДР и Китая высказали свое немыслимое.

Король задумался: «Потребности программистов безграничны, и всегда будут исключения. Такой спрос существует, дайте подумать».

Министр Б, знакомый с C++, поспешно сказал: «Ваше Величество, какова концепция дружественного класса в C++. Например, если дружественный класс LinkedList объявлен в классе Node, LinkedList может получить доступ к свойствам и методам класс узлов».

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

Король согласился: «Да, давайте откажемся от этой идеи, главное, чтобы она была простой. Если он действительно хочет получить доступ к классу B, есть два пути: (1) сделать класс B публичным (2) через класс интерфейса А действовать как агент».

модульный

В мгновение ока король Явы перешел в девятое поколение.

В этот день в гости приехали посланники Python и JavaScript из соседних стран, которые были тепло приняты королем и во время встречи говорили о существовании пакета java.

Хотя пакетный метод Java хорош, у него все же есть большие недостатки.Самый большой недостаток в том, что многие классы в пакете являются общедоступными, из-за чего возникает такая ситуация.

Первоначально я хотел, чтобы org.foo.api предоставлял интерфейс для внешнего мира и позволял клиенту вызывать его, но на самом деле, пока foo.jar помещен в путь к классам, два других пакета, org.foo.impl , org.foo.core Также доступны классы.

Мессенджер JavaScript сказал: «О, я раньше думал, что jar-файл в вашей стране — это повторно используемый модуль, но теперь кажется, что этого далеко не достаточно!»

«Неудивительно, что все говорят, что один из ваших jar-файлов представляет собой сжатый пакет классов, а путь к классам предназначен только для того, чтобы разбить эти классы на части», — рассмеялся мессенджер Python.

Король Ява был немного зол в душе, но не показывал этого на лице: «Как ваша страна добилась этого?»

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

JavaScript даже думать о своем собственном модуле, пакет не и быстро замолчал.

Король Java сказал: «В простых файлах jar отсутствует одна важная функция: скрытие внутренней реализации, и вдова намерена внести важное изменение для определения реальных модулей!»

«Видите? Я планирую использовать файл module-info.java, чтобы определить, какие пакеты в модуле могут быть экспортированы. Только эти экспортированные пакеты могут быть вызваны Клиентом, а остальные пакеты невидимы для Клиента».

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

ServiceLoader

Посланник Python некоторое время смотрел на график и сказал: «Нет, скажем, есть такой код:»

FooService service = new FooServiceImpl();

«Где FooService — это класс в пакете org.foo.api, а FooServiceImpl — это класс в org.foo.impl. Согласно вашим модульным требованиям, клиент не может получить доступ к этому FooServiceImpl, так как же вы можете создать FooService? "

Король Java подумал, что этот мессенджер Python хорошо знаком с моим языком Java, поэтому я не мог сойти со сцены.

«Ваше величество, министр думал, что это можно решить с помощью заводской модели!» Наконец, министр пришел ему на помощь. «Создайте новый класс FooServiceFactory, поместите его в пакет org.foo.api и вызовите его публично, разве этого недостаточно?»

public class FooServiceFactory{    public static FooService getFooService(){        return new FooServiceImpl();    }}скопировать код

Мессенджер Python продолжал давить на него: «Но что раздражает, так это то, что хотя этот FooServiceFactory принадлежит к пакету API, ему нужно знать конкретную реализацию пакета impl. Если вы хотите добавить реализацию FooService, вы должны изменить его. Это все еще неуместно!"

Внезапно король Java погладил себя по голове, кстати, как я мог забыть ServiceLoader?

Я могу разделить исходный модуль на два модуля: org.foo.api для интерфейса и org.foo.provider для реализации.

Специально объявленный в org.foo.provider, этот модуль может обеспечить реализацию FooService!

provides org.foo.api.FooService with  org.foo.provider.FooServiceImpl

Мессенджер Python до сих пор не совсем понимает: «Как его использует клиент?»

«Простой клиентский код можно написать так:»

Iterable<FooService> iter =     ServiceLoader.load(FooService.class);遍历iter,获取FooService并且使用。скопировать код

Таким образом, клиентский код может использовать ServiceLoader для поиска этих конкретных реализаций во время выполнения.Конечно, может быть более одной реализации, и клиент может выбрать одну.

Конечно, JDK должен реализовать этот ServiceLoader, чтобы получить эти конкретные реализации.

«Этот план не разрушает инкапсуляцию, но также обеспечивает достаточную гибкость, что эквивалентно сборке объектов во время выполнения, Ваше Величество Шэнмин!» — льстили министры.

Увидев это, посланник Python замолчал и начал пить, опустив голову.

Мессенджер на JavaScript долго не говорил, все время думал, неужели я немного устарел? У Python есть модули, у Ruby есть модули, а модульность Java идет полным ходом. Модульность значительно улучшает инкапсуляцию. Если вы хотите разрабатывать крупномасштабные проекты, эта модульность незаменима. Подумайте о своих беспорядочных файлах js, пришло время внести изменения...

(над)

Код-фермер развернулся и объяснил суть технологии с рассказами.Более интересные статьи смотрите в »Суть трехлетней статьи кодекса о переворачивании фермера