وسط
معمول هستند
1. مزایا و معایب OOP در مقایسه با برنامه نویسی رویه ای/عملکردی چیست؟
این سوال در تجزیه و تحلیل سوالات برای Juinior وجود داشت و من قبلاً به آن پاسخ داده بودم. این سوال و پاسخ آن را در این قسمت از مقاله سوالات 16 و 17 جستجو کنید .2. تجمیع چه تفاوتی با ترکیب دارد؟
در OOP، انواع مختلفی از تعامل بین اشیاء وجود دارد که تحت مفهوم کلی "Has-A Relationship" متحد شده اند. این رابطه نشان می دهد که یک شی جزء یک شی دیگر است. در عین حال، دو نوع فرعی از این رابطه وجود دارد: ترکیب - یک شیء شیء دیگر را ایجاد می کند و طول عمر شیء دیگر به طول عمر خالق بستگی دارد. تجمع - یک شی یک پیوند (نشانگر) به یک شی دیگر را در طول فرآیند ساخت دریافت می کند (در این مورد، طول عمر شی دیگر به طول عمر سازنده بستگی ندارد). برای درک بهتر، اجازه دهید به یک مثال خاص نگاه کنیم. ما یک کلاس ماشین خاص داریم - Car ، که به نوبه خود دارای فیلدهای داخلی از نوع - Engine و لیست مسافران - List<Passenger> است ، همچنین یک روش برای شروع حرکت دارد - startMoving() :public class Car {
private Engine engine;
private List<Passenger> passengers;
public Car(final List<Passenger> passengers) {
this.engine = new Engine();
this.passengers = passengers;
}
public void addPassenger(Passenger passenger) {
passengers.add(passenger);
}
public void removePassengerByIndex(Long index) {
passengers.remove(index);
}
public void startMoving() {
engine.start();
System.out.println("Машина начала своё движение");
for (Passenger passenger : passengers) {
System.out.println("В машине есть пассажир - " + passenger.getName());
}
}
}
در این مورد، Composition ارتباط بین Car و Engine است ، زیرا عملکرد ماشین مستقیماً به وجود جسم موتور بستگی دارد، زیرا اگر engine = null باشد، یک NullPointerException دریافت خواهیم کرد . به نوبه خود، یک موتور نمی تواند بدون ماشین وجود داشته باشد (چرا به یک موتور بدون ماشین نیاز داریم؟) و نمی تواند در یک نقطه از زمان به چندین ماشین تعلق داشته باشد. این بدان معنی است که اگر شی Car را حذف کنیم ، دیگر ارجاعی به شی Engine وجود نخواهد داشت و به زودی توسط Garbage Collector حذف خواهد شد . همانطور که می بینید، این رابطه بسیار سخت (قوی) است. تجمیع ارتباط بین اتومبیل و مسافر است ، زیرا عملکرد اتومبیل به هیچ وجه به اشیاء از نوع مسافر و تعداد آنها بستگی ندارد. آنها می توانند ماشین را ترک کنند - removePassengerByIndex (شاخص طولانی) یا وارد موارد جدید - addPassenger (مسافر مسافر) ، با وجود این، ماشین به درستی کار خود را ادامه می دهد. به نوبه خود، اشیاء مسافری می توانند بدون شیء اتومبیل وجود داشته باشند . همانطور که می دانید، این ارتباط بسیار ضعیف تر از آنچه در ترکیب می بینیم است. اما این همه چیز نیست، یک شی که از طریق تجمع به دیگری متصل می شود نیز می تواند در همان برهه زمانی یک ارتباط معین با اشیاء دیگر داشته باشد. به عنوان مثال، شما به عنوان یک دانشجوی جاوا، در دوره های انگلیسی، OOP و لگاریتم در یک مقطع زمانی ثبت نام کرده اید، اما در عین حال جزء ضروری آن ها نیستید، که بدون آن عملکرد عادی غیرممکن است (مانند یک معلم).
3. از چه الگوهای GoF در عمل استفاده کرده اید؟ مثال بزن.
من قبلاً به این سؤال پاسخ دادهام، بنابراین فقط یک پیوند به تجزیه و تحلیل میگذارم ، سؤال اول را ببینید. من همچنین یک مقاله تقلب فوق العاده در مورد الگوهای طراحی پیدا کردم که به شدت توصیه می کنم آن را در دسترس داشته باشید.4. شیء پروکسی چیست؟ مثال بزن
پروکسی یک الگوی طراحی ساختاری است که به شما امکان می دهد به جای اشیاء واقعی، اشیاء جایگزین ویژه یا به عبارت دیگر، اشیاء پروکسی را جایگزین کنید. این اشیاء پراکسی تماسهای شی اصلی را قطع میکنند و اجازه میدهند تا مقداری منطق قبل یا بعد از ارسال تماس به اصلی وارد شود. نمونه هایی از استفاده از یک شی پراکسی:-
به عنوان یک پراکسی راه دور - زمانی استفاده می شود که به یک شی از راه دور (یک شی در فضای آدرس متفاوت) نیاز داریم که باید به صورت محلی نمایش داده شود. در این حالت، پروکسی ایجاد اتصال، رمزگذاری، رمزگشایی و غیره را مدیریت می کند، در حالی که مشتری از آن به گونه ای استفاده می کند که گویی شی اصلی واقع در فضای محلی است.
-
به عنوان یک پروکسی مجازی - زمانی استفاده می شود که یک شی با منابع فشرده مورد نیاز است. در این مورد، شی پراکسی به عنوان چیزی شبیه تصویر یک شی واقعی عمل می کند که در واقع هنوز وجود ندارد. هنگامی که یک درخواست واقعی ( فراخوانی متد ) به این شی ارسال می شود، تنها در این صورت شی اصلی بارگذاری می شود و متد اجرا می شود. به این روش اولیه سازی تنبل نیز می گویند؛ این می تواند بسیار راحت باشد، زیرا در برخی شرایط ممکن است شی اصلی مفید نباشد و پس از آن هیچ هزینه ای برای ایجاد آن وجود نخواهد داشت.
-
به عنوان یک پروکسی امنیتی - زمانی استفاده می شود که شما نیاز به کنترل دسترسی به برخی شیء بر اساس حقوق مشتری دارید. یعنی اگر یک کلاینت با حقوق دسترسی از دست رفته سعی کند به شی اصلی دسترسی پیدا کند، پروکسی آن را رهگیری می کند و اجازه نمی دهد.
public interface Processor {
void process();
}
که اجرای آن از منابع بسیار زیادی استفاده می کند، اما در عین حال ممکن است هر بار که برنامه راه اندازی می شود از آن استفاده نشود:
public class HiperDifficultProcessor implements Processor {
@Override
public void process() {
// некоторый сверхсложная обработка данных
}
}
کلاس پروکسی:
public class HiperDifficultProcessorProxy implements Processor {
private HiperDifficultProcessor processor;
@Override
public void process() {
if (processor == null) {
processor = new HiperDifficultProcessor();
}
processor.process();
}
}
بیایید آن را به صورت اصلی اجرا کنیم :
Processor processor = new HiperDifficultProcessorProxy();
// тут тяжеловсеного оригинального an object, ещё не сущетсвует
// но при этом есть an object, который его представляет и у которого можно вызывать его методы
processor.process(); // лишь теперь, an object оригинал был создан
توجه میکنم که بسیاری از فریمورکها از پروکسی استفاده میکنند، و برای Spring این یک الگوی کلیدی است (Spring با آن در داخل و خارج دوخته میشود). اطلاعات بیشتر در مورد این الگو را اینجا بخوانید .
5. چه نوآوری هایی در جاوا 8 اعلام شده است؟
نوآوری های جاوا 8 به شرح زیر است:-
رابط های کاربردی اضافه شده است، در مورد چه نوع جانوری در اینجا بخوانید .
-
عبارات لامبدا، که ارتباط نزدیکی با رابط های کاربردی دارند، در مورد استفاده از آنها در اینجا بیشتر بخوانید .
-
Stream API برای پردازش راحت جمعآوری دادهها اضافه شد ، در اینجا بیشتر بخوانید .
-
پیوندهایی به روش ها اضافه شد .
-
متد forEach() به رابط Iterable اضافه شده است .
-
یک API تاریخ و زمان جدید در بسته java.time اضافه شده است ، تجزیه و تحلیل دقیق در اینجا .
-
API همزمان بهبود یافته
-
با افزودن یک کلاس wrapper اختیاری ، که برای مدیریت صحیح مقادیر تهی استفاده می شود، می توانید یک مقاله عالی در مورد این موضوع را در اینجا پیدا کنید .
-
افزودن توانایی رابطها برای استفاده از روشهای استاتیک و پیشفرض (که در اصل جاوا را به وراثت چندگانه نزدیکتر میکند)، جزئیات بیشتر در اینجا .
-
متدهای جدیدی را به کلاس Collection(removeIf)، spliterator()) اضافه کرد .
-
پیشرفت های جزئی در Java Core.
6. اتصال بالا و اتصال کم چیست؟ مثال بزن.
انسجام بالا یا انسجام بالا مفهومی است که یک طبقه معین شامل عناصری است که ارتباط نزدیکی با یکدیگر دارند و برای هدف خود ترکیب می شوند. به عنوان مثال، همه متدها در کلاس User باید رفتار کاربر را نشان دهند. اگر کلاسی حاوی عناصر نامرتبط باشد، پیوستگی کمی دارد. به عنوان مثال، کلاس User حاوی یک روش اعتبارسنجی آدرس ایمیل:public class User {
private String name;
private String email;
public String getName() {
return this.name;
}
public void setName(final String name) {
this.name = name;
}
public String getEmail() {
return this.email;
}
public void setEmail(final String email) {
this.email = email;
}
public boolean isValidEmail() {
// некоторая логика валидации емейла
}
}
ممکن است کلاس کاربر مسئول ذخیره آدرس ایمیل کاربر باشد، اما نه برای تأیید اعتبار یا ارسال ایمیل. بنابراین، برای دستیابی به انسجام بالا، روش اعتبارسنجی را به یک کلاس کاربردی جداگانه منتقل می کنیم:
public class EmailUtil {
public static boolean isValidEmail(String email) {
// некоторая логика валидации емейла
}
}
و در صورت نیاز از آن استفاده می کنیم (مثلاً قبل از ذخیره کاربر). اتصال کم یا اتصال کم مفهومی است که وابستگی متقابل کم بین ماژول های نرم افزار را توصیف می کند. اساساً، وابستگی متقابل این است که چگونه تغییر یکی مستلزم تغییر دیگری است. دو کلاس در صورتی که به هم مرتبط باشند، یک جفت قوی (یا کوپلینگ محکم) دارند. به عنوان مثال، دو کلاس مشخص که ارجاعات را به یکدیگر ذخیره می کنند و متدهای یکدیگر را فراخوانی می کنند. توسعه و نگهداری کلاسهایی که با هم جفت شدهاند آسانتر است. از آنجایی که آنها مستقل از یکدیگر هستند، می توان آنها را به طور موازی توسعه و آزمایش کرد. علاوه بر این، آنها را می توان تغییر و به روز رسانی بدون تاثیر روی یکدیگر. بیایید به نمونه ای از کلاس های قویا جفت شده نگاه کنیم. ما چند کلاس دانشجویی داریم:
public class Student {
private Long id;
private String name;
private List<Lesson> lesson;
}
که حاوی لیستی از دروس است:
public class Lesson {
private Long id;
private String name;
private List<Student> students;
}
هر درس حاوی پیوندی به دانش آموزان شرکت کننده است. گرفتن فوق العاده قوی، فکر نمی کنید؟ چگونه می توانید آن را کاهش دهید؟ اول، بیایید مطمئن شویم که دانش آموزان لیستی از موضوعات ندارند، بلکه فهرستی از شناسه های خود را دارند:
public class Student {
private Long id;
private String name;
private List<Long> lessonIds;
}
ثانیاً، کلاس درس نیازی به اطلاع از همه دانش آموزان ندارد، بنابراین بیایید فهرست آنها را به طور کلی حذف کنیم:
public class Lesson {
private Long id;
private String name;
}
بنابراین خیلی راحت تر شد و ارتباط بسیار ضعیف تر شد، فکر نمی کنید؟
OOP
7. چگونه می توان وراثت چندگانه را در جاوا پیاده سازی کرد؟
وراثت چندگانه یکی از ویژگی های مفهوم شی گرا است که در آن یک کلاس می تواند ویژگی های بیش از یک کلاس والد را به ارث ببرد. مشکل زمانی ایجاد می شود که متدهایی با امضای یکسان در کلاس فوق و زیر کلاس وجود داشته باشد. هنگام فراخوانی یک متد، کامپایلر نمی تواند تعیین کند که کدام متد کلاس باید فراخوانی شود، و حتی در هنگام فراخوانی متد کلاس که اولویت دارد. بنابراین، جاوا از وراثت چندگانه پشتیبانی نمی کند! اما نوعی خلأ وجود دارد که در ادامه در مورد آن صحبت خواهیم کرد. همانطور که قبلاً اشاره کردم، با انتشار جاوا 8، قابلیت داشتن روش های پیش فرض به رابط ها اضافه شد . اگر کلاسی که رابط را پیادهسازی میکند، این متد را لغو نکند، از این پیادهسازی پیشفرض استفاده میشود (لازم نیست روش پیشفرض، مانند پیادهسازی یک انتزاعی، نادیده گرفته شود). در این صورت امکان پیاده سازی اینترفیس های مختلف در یک کلاس و استفاده از روش های پیش فرض آنها وجود دارد. بیایید به یک مثال نگاه کنیم. ما چند رابط پروازی داریم، با یک متد fly() پیشفرض :public interface Flyer {
default void fly() {
System.out.println("Я лечу!!!");
}
}
رابط واکر، با متد walk() پیش فرض :
public interface Walker {
default void walk() {
System.out.println("Я хожу!!!");
}
}
رابط شناگر، با متد swim() :
public interface Swimmer {
default void swim() {
System.out.println("Я плыву!!!");
}
}
خوب، حالا بیایید همه اینها را در یک کلاس اردک پیاده سازی کنیم:
public class Duck implements Flyer, Swimmer, Walker {
}
و بیایید همه روش های اردک خود را اجرا کنیم:
Duck donald = new Duck();
donald.walk();
donald.fly();
donald.swim();
در کنسول ما دریافت خواهیم کرد:
- متدها را در واسط ها تغییر نام دهید تا با یکدیگر متفاوت باشند.
- این روش های بحث برانگیز را در کلاس پیاده سازی لغو کنید.
- از کلاسی که این متدهای بحث برانگیز را پیاده سازی می کند ارث بری کنید (آنگاه کلاس شما دقیقاً از پیاده سازی آن استفاده خواهد کرد).
8. تفاوت بین متدهای final، final و finalize() چیست؟
final یک کلمه کلیدی است که برای قرار دادن یک محدودیت بر روی یک کلاس، متد یا متغیر استفاده می شود، به معنای محدودیت:- برای یک متغیر - پس از مقداردهی اولیه، متغیر قابل تعریف مجدد نیست.
- برای یک متد، متد را نمی توان در یک زیر کلاس (کلاس جانشین) نادیده گرفت.
- برای یک کلاس - کلاس را نمی توان به ارث برد.
GO TO FULL VERSION