인터페이스와 추상 클래스의 차이를 어떻게 설명해야 하는가?
내 인터뷰 중 하나에서 인터페이스와 추상 수업의 차이점을 설명해 달라는 요청을 받았다.
내 대답은 다음과 같다.
Java 인터페이스의 방법은 암묵적으로 추상적이며 구현될 수 없다.Java 추상 클래스는 기본 동작을 구현하는 인스턴스 메서드를 가질 수 있다.
Java 인터페이스에서 선언된 변수는 기본적으로 최종이다.추상 클래스는 최종 변수가 아닌 변수를 포함할 수 있다.
Java 인터페이스의 구성원은 기본적으로 공용이다.자바 추상 수업은 개인, 보호 등과 같은 클래스 멤버들의 일반적인 맛을 가질 수 있다.
자바 인터페이스는 키워드 "이행"을 사용하여 구현되어야 하며, 자바 추상 클래스는 키워드 "확장"을 사용하여 확장되어야 한다.
인터페이스는 다른 Java 인터페이스만 확장할 수 있으며, 추상 클래스는 다른 Java 클래스를 확장하고 여러 Java 인터페이스를 구현할 수 있다.
Java 클래스는 여러 인터페이스를 구현할 수 있지만 하나의 추상 클래스만 확장할 수 있다.
그러나 인터뷰 진행자는 만족하지 않았고, 이 묘사가 '책략적인 지식'을 나타낸다고 내게 말했다.
그는 나에게 인터페이스보다 추상적인 수업을 언제 선택할 것인지, 실용적인 예를 들어 설명하면서 좀 더 실용적인 답변을 부탁했다.
어디서부터 제가 잘못했을까요?
내가 먼저 예를 하나 들겠다.
public interface LoginAuth{
public String encryptPassword(String pass);
public void checkDBforUser();
}
응용 프로그램에 3개의 데이터베이스가 있다고 가정해 보십시오.그런 다음 해당 데이터베이스에 대한 모든 구현은 위의 두 가지 방법을 정의해야 한다.
public class DBMySQL implements LoginAuth{
// Needs to implement both methods
}
public class DBOracle implements LoginAuth{
// Needs to implement both methods
}
public class DBAbc implements LoginAuth{
// Needs to implement both methods
}
하지만 만약encryptPassword()
데이터베이스에 의존하지 않고 각 클래스에 대해 동일한가?그렇다면 위의 것은 좋은 접근법이 아닐 것이다.
대신 다음과 같은 방법을 고려하십시오.
public abstract class LoginAuth{
public String encryptPassword(String pass){
// Implement the same default behavior here
// that is shared by all subclasses.
}
// Each subclass needs to provide their own implementation of this only:
public abstract void checkDBforUser();
}
이제 각 아동 계층에서 우리는 오직 하나의 방법, 즉 데이터베이스에 의존하는 방법만을 구현하면 된다.
이 세상에 완벽한 것은 없다.그들은 좀 더 실용적인 접근을 기대했을지도 모른다.
하지만 당신의 설명이 끝난 후에 당신은 약간 다른 접근법으로 이 선을 추가할 수 있다.
인터페이스는 소프트웨어 개발의 여러 팀 간에 공통의 이해 문서로서 작용하는 규칙(규칙을 무시하거나 피할 수 없는 구현을 주어야 하기 때문에 규칙)이다.
인터페이스는 무엇을 해야 할지 아이디어를 주지만 어떻게 해야 할지 알려주지 않는다.따라서 구현은 주어진 규칙(수단의 서명)을 준수함으로써 개발자에게 완전히 의존한다.
추상 클래스는 추상 선언, 구체적인 구현 또는 둘 다를 포함할 수 있다.
추상적 선언은 지켜야 할 규칙과 같고 구체적인 구현은 지침과 같다(있는 그대로 사용하거나 자신의 구현을 재정의하고 부여하여 무시할 수 있다).
또한 서명이 동일한 방법이 다른 맥락에서 행동을 변화시킬 수 있는 방법은 다른 맥락에서 그에 따라 구현하기 위한 규칙으로서 인터페이스 선언으로 제공된다.
편집: Java 8은 인터페이스에서 기본 방법과 정적 방법을 쉽게 정의한다.
public interface SomeInterfaceOne {
void usualAbstractMethod(String inputString);
default void defaultMethod(String inputString){
System.out.println("Inside SomeInterfaceOne defaultMethod::"+inputString);
}
}
이제 클래스가 SomeInterface를 구현할 때, 기본 인터페이스 방법에 대한 구현을 의무적으로 제공하는 것은 아니다.
다음 방법을 사용하는 다른 인터페이스가 있는 경우:
public interface SomeInterfaceTwo {
void usualAbstractMethod(String inputString);
default void defaultMethod(String inputString){
System.out.println("Inside SomeInterfaceTwo defaultMethod::"+inputString);
}
}
자바는 컴파일러가 어떤 슈퍼클래스 방식을 사용할지 결정할 수 없는 '다이아몬드 문제'가 발생하기 때문에 다중 클래스 연장을 허용하지 않는다.기본 방법을 사용하면 인터페이스에서도 다이아몬드 문제가 발생할 수 있다.왜냐하면 한 클래스가 두 가지 모두를 구현하고 있기 때문이다.
SomeInterfaceOne and SomeInterfaceTwo
그리고 일반적인 기본 방법을 구현하지 않고 컴파일러가 어떤 방법을 선택할지 결정할 수 없다.이 문제를 방지하려면, 자바 8에서 다른 인터페이스의 공통 기본 방법을 구현해야 한다.어떤 클래스가 위의 두 인터페이스를 모두 구현하는 경우, 디폴트메소드() 방법에 대한 구현을 제공해야 한다. 그렇지 않으면 컴파일러가 컴파일 시간 오류를 발생시킬 것이다.
사용과 실행의 실제적인 차이를 잘 요약해 주었지만 의미에서의 차이에 대해서는 아무 말도 하지 않았다.
인터페이스는 구현 클래스가 가질 행동에 대한 설명이다.구현 클래스는 해당 클래스에 사용할 수 있는 이러한 방법을 가질 수 있음을 보장한다.그것은 기본적으로 학급이 해야 할 계약이나 약속이다.
추상 클래스는 반복적으로 생성될 필요가 없는 행동을 공유하는 다른 하위 클래스의 기본이다.하위 클래스는 동작을 완료해야 하며 사전 정의된 동작을 재정의할 수 있는 옵션이 있어야 함(단, 다음과 같이 정의되지 않은 경우)final
또는private
).
좋은 예는 다음에서 찾을 것이다.java.util
다음과 같은 인터페이스를 포함하는 패키지List
그리고 같은 추상적인 수업들AbstractList
인터페이스가 이미 구현되어 있는 경우.공식 문서에는 다음이 설명되어 있다.AbstractList
아래와 같이
이 클래스는 "임의 액세스" 데이터 저장소(예: 어레이)에 의해 지원되는 이 인터페이스를 구현하는 데 필요한 노력을 최소화하기 위해 목록 인터페이스의 골격 구현을 제공한다.
인터페이스는 싱글톤 변수(공용 정적 최종)와 공개 추상적 방법으로 구성된다.우리는 보통 우리가 무엇을 해야 할지 알고 있지만 어떻게 해야 할지 모를 때 인터페이스를 실시간으로 사용하는 것을 선호한다.
이 개념은 예시로 더 잘 이해할 수 있다.
결제 클래스를 고려하십시오.결제는 페이팔, 신용카드 등 여러 가지 방법으로 할 수 있다.그래서 우리는 보통 Payment를 우리의 인터페이스로 받아들인다.makePayment()
Method와 CreditCard와 PayPal은 두 가지 구현 클래스다.
public interface Payment
{
void makePayment();//by default it is a abstract method
}
public class PayPal implements Payment
{
public void makePayment()
{
//some logic for PayPal payment
//e.g. Paypal uses username and password for payment
}
}
public class CreditCard implements Payment
{
public void makePayment()
{
//some logic for CreditCard payment
//e.g. CreditCard uses card number, date of expiry etc...
}
}
위의 예에서 CreditCard와 PayPal은 두 가지 구현 클래스/전략이다.인터페이스는 또한 추상적인 클래스에 의해 달성될 수 없는 자바에서의 다중 상속의 개념을 우리에게 허용한다.
우리는 우리가 무엇을 해야 할지를 아는 특징과 우리가 어떻게 해야 할지를 아는 다른 특징들이 있을 때 추상적인 수업을 선택한다.
다음 예를 고려해 보십시오.
public abstract class Burger
{
public void packing()
{
//some logic for packing a burger
}
public abstract void price(); //price is different for different categories of burgers
}
public class VegBerger extends Burger
{
public void price()
{
//set price for a veg burger.
}
}
public class NonVegBerger extends Burger
{
public void price()
{
//set price for a non-veg burger.
}
}
만약 우리가 미래에 방법(구체적/추상적)을 주어진 추상적 클래스에 추가한다면, 구현 클래스는 그것의 코드를 변경할 필요가 없을 것이다.그러나 향후 인터페이스에 메서드를 추가할 경우, 해당 인터페이스를 구현한 모든 클래스에 구현을 추가해야 하며 그렇지 않으면 컴파일 시간 오류가 발생한다.
다른 차이점들이 있지만 이것들은 당신의 면접관이 기대했던 것일 수도 있는 주요한 차이점들이다.이것이 도움이 되었기를 바란다.
1.1 추상 클래스와 인터페이스의 차이
1.1.1. Abstract classes versus interfaces in Java 8
1.1.2. Conceptual Difference:
1.2 Java 8의 인터페이스 기본 방법
1.2.1. What is Default Method?
1.2.2. ForEach method compilation error solved using Default Method
1.2.3. Default Method and Multiple Inheritance Ambiguity Problems
1.2.4. Important points about java interface default methods:
1.3 Java 인터페이스 정적 방법
1.3.1. Java Interface Static Method, code example, static method vs default method
1.3.2. Important points about java interface static method:
1.4 Java 기능 인터페이스
1.1.1. Java 8의 추상 클래스 대 인터페이스
Java 8 인터페이스 변경에는 인터페이스의 정적 방법과 기본 방법이 포함된다.자바 8 이전에는 인터페이스에 메서드 선언만 있을 수 있었다.하지만 자바 8에서 인터페이스에 기본 방법과 정적 방법을 사용할 수 있다.
디폴트 메소드를 도입한 후 인터페이스와 추상 클래스가 동일한 것으로 보인다.그러나 자바 8에서는 여전히 다른 개념이다.
추상 클래스는 생성자를 정의할 수 있다.그들은 더 체계적이고 그들과 관련된 상태를 가질 수 있다.대조적으로, 디폴트 방법은 특정 구현의 상태를 참조하지 않고 다른 인터페이스 방법을 호출하는 조건에서만 구현될 수 있다.따라서 서로 다른 목적으로 사용하는 것과 둘 중 하나를 선택하는 것은 시나리오 상황에 따라 달라진다.
1.1.2. 개념적 차이:
추상 클래스는 인터페이스의 골격(즉, 부분) 구현에 유효하지만 일치하는 인터페이스 없이는 존재할 수 없다.
따라서 추상 클래스가 효과적으로 저시력, 인터페이스의 골격 구현으로 축소될 때, 기본 방법 또한 이를 제거할 수 있는가?결정적으로: 아니오! 인터페이스를 구현하는 것은 거의 항상 기본 방법이 부족한 클래스 구축 도구의 일부 또는 전부를 필요로 한다.그리고 만약 어떤 인터페이스가 그렇지 않다면, 그것은 분명히 특별한 경우일 것이며, 그것은 여러분을 잘못된 길로 인도하지 말아야 한다.
1.2 Java 8의 인터페이스 기본 방법
Java 8은 개발자가 이러한 인터페이스의 기존 구현을 중단하지 않고 인터페이스에 새로운 방법을 추가할 수 있는 "기본 방법" 또는 (Defender methods) 새로운 기능을 도입한다.그것은 구체적인 클래스가 그 방법에 대한 구현을 제공하지 못하는 상황에서 디폴트로 사용할 구현을 인터페이스가 정의할 수 있도록 유연성을 제공한다.
작동 방식을 이해하기 위한 작은 예를 들어보자.
public interface OldInterface {
public void existingMethod();
default public void newDefaultMethod() {
System.out.println("New default method"
+ " is added in interface");
}
}
다음 클래스는 Java JDK 8에서 성공적으로 컴파일될 것이다.
public class OldInterfaceImpl implements OldInterface {
public void existingMethod() {
// existing implementation is here…
}
}
OldInterfaceImpl 인스턴스를 생성하는 경우:
OldInterfaceImpl obj = new OldInterfaceImpl ();
// print “New default method add in interface”
obj.newDefaultMethod();
1.2.1. 기본 방법:
기본 메서드는 결코 최종적이지 않으며 동기화할 수 없으며 오브젝트의 메서드를 재정의할 수 없다.그것들은 항상 공개적이어서 짧고 재사용 가능한 방법을 쓰는 능력을 심각하게 제한한다.
기본 방법은 구현을 포함하므로 클래스에 영향을 미치지 않고 인터페이스에 제공될 수 있다.구현과 함께 정의된 인터페이스의 각 추가 방법이 영향을 받지 않는 경우, 어떤 구현 클래스도 영향을 받지 않는다.구현 클래스는 인터페이스가 제공하는 기본 구현을 재정의할 수 있다.
기본 방법은 이러한 인터페이스의 이전 구현을 중단하지 않고 기존 인터페이스에 새로운 기능을 추가할 수 있다.
기본 메서드가 포함된 인터페이스를 확장하면 다음과 같은 작업을 수행할 수 있으며,
- 기본 메서드를 재정의하지 마십시오. 그러면 기본 메서드가 상속됩니다.
- 하위 클래스에서 재정의하는 다른 방법과 유사한 기본 메서드를 재정의하십시오.
- 하위 클래스가 해당 메서드를 재정의하도록 강제하는 기본 메서드를 추상적으로 다시 닫으십시오.
1.2.2. ForExecution 기본 방법을 사용하여 해결된 각 방법 컴파일 오류
Java 8의 경우 JDK 컬렉션이 확장되었으며, 각 메서드는 전체 컬렉션에 추가된다(양다와 함께 작동).전통적인 방식으로 볼 때, 코드는 아래와 같이 보인다.
public interface Iterable<T> {
public void forEach(Consumer<? super T> consumer);
}
따라서 이 결과로 각 클래스가 컴파일 오류로 인해 기존 구현을 변경하지 않도록 필요한 구현과 함께 추가된 기본 방법이 있다.
기본 방법의 반복 가능한 인터페이스는 다음과 같다.
public interface Iterable<T> {
public default void forEach(Consumer
<? super T> consumer) {
for (T t : this) {
consumer.accept(t);
}
}
}
동일한 메커니즘이 구현 클래스를 위반하지 않고 JDK 인터페이스에서 스트림을 추가하는 데 사용되어 왔다.
1.2.3. 기본 방법 및 다중 상속 모호성 문제
자바 클래스는 여러 인터페이스를 구현할 수 있고 각 인터페이스는 동일한 방법 서명으로 기본 방법을 정의할 수 있으므로, 상속된 방법은 서로 충돌할 수 있다.
아래 예제를 고려하십시오.
public interface InterfaceA {
default void defaultMethod(){
System.out.println("Interface A default method");
}
}
public interface InterfaceB {
default void defaultMethod(){
System.out.println("Interface B default method");
}
}
public class Impl implements InterfaceA, InterfaceB {
}
위의 코드는 다음과 같은 오류와 함께 컴파일되지 않을 것이다.
java: 클래스 포함 인터페이스A 및 인터페이스B 유형에서 defaultMethod()와 관련 없는 기본값을 상속함
이 클래스를 수정하려면 다음과 같은 기본 방법 구현을 제공해야 한다.
public class Impl implements InterfaceA, InterfaceB {
public void defaultMethod(){
}
}
또한, 자체 구현이 아닌 슈퍼 인터페이스에서 제공하는 디폴트 구현을 실행하려면 다음과 같이 할 수 있다.
public class Impl implements InterfaceA, InterfaceB {
public void defaultMethod(){
// existing code here..
InterfaceA.super.defaultMethod();
}
}
우리는 새로운 방법의 일부로 어떤 기본 구현이나 둘 다 선택할 수 있다.
1.2.4. 자바 인터페이스 기본 방법에 대한 중요 사항:
- 자바 인터페이스 디폴트 방법은 구현 클래스를 위반할 염려 없이 인터페이스를 확장하는 데 도움이 될 것이다.
- 자바 인터페이스 기본 방법은 인터페이스와 추상 클래스 간의 차이를 줄여준다.
- Java 8 인터페이스 기본 방법은 인터페이스 자체에서 모든 수집 클래스 방법이 제공될 수 있는 것과 같은 유틸리티 클래스를 피하는 데 도움이 될 것이다.
- Java 인터페이스 기본 방법은 기본 구현 클래스를 제거하는 데 도움이 되며, 기본 구현을 제공할 수 있으며 구현 클래스는 재정의할 클래스를 선택할 수 있다.
- 인터페이스에 디폴트 메소드를 도입하는 주요 이유 중 하나는 자바 8의 콜렉션 API를 강화하여 람다 식을 지원하기 위함이다.
- 계층의 클래스가 동일한 서명의 메서드를 가지고 있는 경우, 기본 메서드는 무관하게 된다.기본 메서드는 java.lang에서 메서드를 재정의할 수 없다.목적어. 그 추리는 매우 간단해. 왜냐하면 오브젝트는 모든 자바 클래스의 기본 클래스거든.따라서 인터페이스에서 객체 클래스 메서드를 기본 메서드로 정의하더라도 객체 클래스 메서드는 항상 사용되기 때문에 무용지물이 될 것이다.그렇기 때문에 혼동을 피하기 위해 Object 클래스 메서드를 재정의하는 기본 메서드를 가질 수 없다.
- Java 인터페이스 기본 방법을 Defender 메소드 또는 가상 확장 메소드라고도 한다.
리소스 링크:
1.3 Java 인터페이스 정적 방법
1.3.1. Java 인터페이스 정적 방법, 코드 예제, 정적 방법 대 기본 방법
Java 인터페이스 정적 방법은 구현 클래스에서 재정의할 수 없다는 점을 제외하면 기본 방법과 유사하다.이 기능은 구현 클래스에서 실행 불량으로 인한 원치 않는 결과를 방지하는 데 도움이 된다.이것을 간단한 예로 살펴보자.
public interface MyData {
default void print(String str) {
if (!isNull(str))
System.out.println("MyData Print::" + str);
}
static boolean isNull(String str) {
System.out.println("Interface Null Check");
return str == null ? true : "".equals(str) ? true : false;
}
}
이제 제대로 구현되지 않은 isNull() 방식을 사용하는 구현 클래스를 봅시다.
public class MyDataImpl implements MyData {
public boolean isNull(String str) {
System.out.println("Impl Null Check");
return str == null ? true : false;
}
public static void main(String args[]){
MyDataImpl obj = new MyDataImpl();
obj.print("");
obj.isNull("abc");
}
}
isNull(String str)은 단순한 클래스 방법이며 인터페이스 방법을 재정의하는 것이 아니라는 점에 유의하십시오.예를 들어 isNull() 방법에 @Override 주석을 추가하면 컴파일러 오류가 발생한다.
이제 애플리케이션을 실행하면 다음과 같은 결과를 얻을 수 있다.
인터페이스 Null 검사
Null Check 포함
인터페이스 방법을 정적에서 기본값으로 만들면 다음과 같은 결과를 얻을 수 있을 것이다.
Null Check 포함
MyData Print:
Null Check 포함
Java 인터페이스 정적 메서드는 인터페이스 메서드에만 표시되며, MyDataImpl 클래스에서 isNull() 메서드를 제거하면 MyDataImpl 개체에 사용할 수 없다.그러나 다른 정적 방법과 마찬가지로 우리는 클래스 이름을 사용하여 인터페이스 정적 방법을 사용할 수 있다.예를 들어, 유효한 문장은 다음과 같다.
boolean result = MyData.isNull("abc");
1.3.2. 자바 인터페이스 정적 방법에 대한 중요 사항:
- Java 인터페이스 정적 방법은 인터페이스의 일부로서 구현 클래스 객체에 사용할 수 없다.
- Java 인터페이스 정적 방법은 Null Check, 수집 정렬 등과 같은 유틸리티 방법을 제공하는 데 좋다.
- Java 인터페이스 정적 방법은 구현 클래스가 이를 재정의하지 못하게 함으로써 보안을 제공하는 데 도움이 된다.
- 오브젝트 클래스 메서드에 대한 인터페이스 정적 메서드를 정의할 수 없으며, "이 정적 메서드는 오브젝트에서 인스턴스 메서드를 숨길 수 없음"으로 컴파일러 오류가 발생할 것이다.이것은 Java에서는 허용되지 않기 때문이다. 왜냐하면 Object는 모든 클래스의 기본 클래스이고 우리는 하나의 클래스 레벨의 정적 방법과 동일한 서명의 다른 인스턴스 방법을 가질 수 없기 때문이다.
- 우리는 Java 인터페이스 정적 방법을 사용하여 Collections와 같은 유틸리티 클래스를 제거하고 그것의 모든 정적 방법을 찾기 쉽고 사용하기 쉬운 해당 인터페이스로 이동시킬 수 있다.
1.4 Java 기능 인터페이스
게시물을 마무리하기 전에 기능 인터페이스에 대해 간략하게 소개하고자 한다.정확히 하나의 추상적인 방법을 가진 인터페이스를 기능 인터페이스라고 한다.
새 주십시요.@FunctionalInterface
인터페이스를 기능 인터페이스로 표시하기 위해 도입되었다.@FunctionalInterface
주석은 기능 인터페이스에서 우연히 추상적 방법이 추가되는 것을 방지하기 위한 기능이다.그것은 선택적이지만 그것을 사용하는 것은 좋은 습관이다.
기능적 인터페이스는 우리가 람다 표현을 사용하여 그것들을 인스턴스화할 수 있기 때문에 자바 8의 오래 기다리며 많은 사람들이 찾고 있다.기능 인터페이스 번들로 구성된 새로운 패키지 java.util.function이 추가되어 람다 식과 메서드 참조를 위한 타겟 유형을 제공한다.향후 게시물에서 기능 인터페이스와 람다 표현을 살펴보겠다.
리소스 위치:
첫 번째 문구를 제외한 모든 문장이 유효함(Java 8 릴리스 이후):
Java 인터페이스의 방법은 암묵적으로 추상적이며 구현될 수 없다.
설명서 페이지에서:
인터페이스는 클래스와 유사한 참조 유형으로 상수, 메서드 서명, 기본 메서드, 정적 메서드 및 중첩 유형만 포함할 수 있다.
메서드 본체는 기본 메서드와 정적 메서드에 대해서만 존재한다.
기본 메서드:
인터페이스는 기본 메서드를 가질 수 있지만 추상 클래스의 추상 메서드와 다르다.
기본 방법을 사용하면 라이브러리의 인터페이스에 새로운 기능을 추가하고 이러한 인터페이스의 이전 버전에 대해 작성된 코드와의 이진 호환성을 보장할 수 있다.
기본 메서드가 포함된 인터페이스를 확장할 때 다음을 수행할 수 있다.
- 확장된 인터페이스가 기본 메서드를 상속할 수 있는 기본 메서드는 전혀 언급하지 마십시오.
- 기본 메서드를 다시 클리닝하여
abstract
. - 기본 메서드를 재정의하십시오.
정적 메서드:
기본 방법 외에도 인터페이스에서 정적 방법을 정의할 수 있다.(정적 방법은 어떤 물체보다는 그것이 정의되는 클래스와 연관되는 방법이다.클래스의 모든 인스턴스는 정적 방법을 공유한다.)
이렇게 하면 라이브러리에서 도우미 방법을 쉽게 구성할 수 있다.
문서 : Documentation page the Lateroso의 예제보보보보보보보보보보보보보보보보보보보보.interface
하고 있다static
그리고default
방법들
import java.time.*;
public interface TimeClient {
void setTime(int hour, int minute, int second);
void setDate(int day, int month, int year);
void setDateAndTime(int day, int month, int year,
int hour, int minute, int second);
LocalDateTime getLocalDateTime();
static ZoneId getZoneId (String zoneString) {
try {
return ZoneId.of(zoneString);
} catch (DateTimeException e) {
System.err.println("Invalid time zone: " + zoneString +
"; using default time zone instead.");
return ZoneId.systemDefault();
}
}
default ZonedDateTime getZonedDateTime(String zoneString) {
return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
}
}
다음 지침을 사용하여 인터페이스 또는 추상 클래스를 사용할지 선택하십시오.
인터페이스:
- 계약을 정의하려면(가능한 경우 상태 비저장 - 변수 없음)
- 관련 없는 클래스를 연결할 수 있는 기능이 있음.
- 공용 상수 변수를 선언하려면(불가능한 상태)
추상 클래스:
밀접하게 관련된 여러 클래스 간에 코드를 공유하십시오.그것은 관계다.
관련 등급 간 공통 상태 공유(콘크리트 등급에서 상태 수정 가능)
관련 게시물:
이러한 예들을 살펴봄으로써, 당신은 그것을 이해할 수 있다.
관련 없는 클래스는 인터페이스를 통한 기능을 가질 수 있지만 관련 클래스는 기본 클래스의 확장을 통해 동작을 변화시킨다.
너의 설명은 점잖게 보이지만, 교과서에서 다 읽은 것처럼 보였을까? :-/
내가 더 신경쓰는 것은, 너의 예가 얼마나 견고했느냐 하는 것이다.추상적인 것과 인터페이스의 차이점을 거의 모두 포함시키려 하셨습니까?
개인적으로, 나는 이 링크를 제안한다: http://mindprod.com/jgloss/interfacevsabstract.html#TABLE
모든 차이점 리스트를 위해..
그것이 당신과 다른 모든 독자들의 앞으로의 인터뷰에 도움이 되기를 바란다.
많은 후배 개발자들은 인터페이스, 추상적이고 구체적인 클래스를 같은 것의 약간의 변화로 생각하는 실수를 저지르고, 그 중 하나를 순전히 기술적 이유로 선택한다.다중 상속이 필요한가? 공통적인 방법을 쓸 곳이 필요한가? 구체적인 수업 말고 다른 일로 신경 쓸 필요가 있을까?이것은 틀렸고, 이러한 질문들 속에 숨겨져 있는 것이 주요 문제점이다: "나". 스스로 코드를 작성할 때, 당신은 다른 현재나 미래의 개발자들이 당신의 코드를 사용하거나 가지고 작업하는 것을 거의 생각하지 않는다.
인터페이스와 추상 클래스는 기술적 관점에서 분명히 유사하지만 전혀 다른 의미와 목적을 가지고 있다.
요약
인터페이스는 일부 구현이 당신을 위해 이행할 계약을 정의한다.
추상 클래스는 구현이 재사용할 수 있는 기본 동작을 제공한다.
위의 두 가지 요점은 내가 인터뷰를 할 때 찾고 있는 것이고, 충분히 요약된 것이다.자세한 내용은 계속 읽어보십시오.
대체 요약
- 인터페이스는 공용 API를 정의하기 위한 것이다.
- 추상 클래스는 내부용 및 SPI 정의용입니다.
예시별
다르게 말하면, 콘크리트 수업은 실제 작업을 매우 구체적인 방법으로 한다.예를 들어,ArrayList
메모리 인접 영역을 사용하여 객체 목록을 컴팩트하게 저장하여 빠른 랜덤 액세스, 반복 및 인플레이스 변경을 제공하지만 삽입, 삭제 및 때로는 추가에도 서툴다.LinkedList
객체 목록을 저장하기 위해 이중 연결 노드를 사용하며, 대신 빠른 반복, 인플레이스 변경, 삽입/삽입/제거 기능을 제공하지만 임의 액세스에서는 형편없다.이 두 가지 유형의 목록은 서로 다른 사용 사례에 최적화되어 있으며, 어떻게 사용할 것인지가 매우 중요하다.상호작용을 많이 하는 리스트에서 성과를 짜내려고 할 때, 그리고 리스트의 종류를 고를 때, 당신은 당신이 인스턴스화하고 있는 리스트를 신중하게 선택해야 한다.
반면에, 목록의 상위 사용자들은 그것이 실제로 어떻게 구현되는지에 대해 별로 신경 쓰지 않으며, 그들은 이러한 세부사항으로부터 격리되어야 한다.자바가 그 사실을 폭로하지 않았다고 가정해 보자.List
인터페이스, 그러나 콘크리트만 가지고 있었다.List
사실 그런 수업은LinkedList
바로 지금이야모든 Java 개발자는 무작위 액세스를 방지하거나, 액세스 속도를 높이기 위해 캐시를 추가하거나, 재구성을 하는 등 구현 세부사항에 맞게 코드를 맞춤화했을 수 있음ArrayList
비록 그것이 실제로 작동하는 다른 모든 코드들과 양립할 수 없더라도 그들 스스로.List
그건 끔찍할 거야그러나 이제 자바 마스터들이 실제로 링크된 목록이 대부분의 실제 사용 사례에 대해 끔찍하다는 것을 깨닫고, 유일한 사용 사례로 어레이 목록으로 전환하기로 결정했다고 상상해 보십시오.List
수업할 수 있는 수업할 수 있는 수업이것은 세계의 모든 자바 프로그램의 성능에 영향을 미칠 것이고, 사람들은 그것을 좋아하지 않을 것이다.그리고 그 주범은 이행내역이 입수 가능했다는 것이고, 개발자들은 그 세부사항들이 그들이 의지할 수 있는 영구적인 계약이라고 가정했다.구현 세부사항을 숨기고 추상적인 계약만 정의하는 것이 중요한 이유다.이것이 인터페이스의 목적이다: 미래의 업데이트에 따라 변경될 수 있는 내부 세부사항에 맞게 프로그래머가 코드를 수정하도록 유도할 모든 배짱을 노출시키지 않고, 어떤 방법이 수용하는 입력의 종류와 예상되는 출력물의 종류를 정의한다.
인터페이스와 콘크리트 클래스 사이에 추상적인 클래스가 있다.그것은 구현이 공통적이거나 지루한 코드를 공유하도록 돕도록 되어 있다.예를 들어,AbstractCollection
에 대한 기본 구현 제공isEmpty
사이즈는 0,contains
반복해서 비교하자면addAll
되풀이하여add
, 등등.이를 통해 구현은 데이터를 실제로 저장하고 검색하는 방법이라는 서로 구별되는 중요한 부분에 초점을 맞출 수 있다.
다른 관점: API 대 SPI
인터페이스는 코드의 다른 부분들 사이의 낮은 코팅의 게이트웨이다.그들은 내부적으로 무언가가 변할 때 모든 도서관 사용자를 파괴하지 않고 도서관이 존재하고 진화할 수 있도록 한다.그것은 응용 프로그램 프로그래밍 클래스가 아니라 응용 프로그램 프로그래밍 인터페이스라고 불린다.소규모로, 그들은 또한 잘 문서화된 인터페이스를 통해 서로 다른 모듈들을 분리함으로써 대규모 프로젝트에서 여러 개발자들이 성공적으로 협업할 수 있도록 한다.
추상 클래스는 어느 정도의 구현 세부사항을 가정하여 인터페이스를 구현할 때 사용되는 고코션 도우미다.또는 SPI, 서비스 공급자 인터페이스를 정의하는 데 추상 클래스가 사용된다.
API와 SPI의 차이는 미묘하지만 중요한데 API의 경우, API의 경우 누가 API를 사용하는지, SPI의 경우 누가 API를 구현하는지에 초점을 맞춘다.
API에 메소드를 추가하는 것은 쉽지만, API의 모든 기존 사용자들은 여전히 컴파일할 것이다.모든 서비스 제공업체(구체적인 구현)는 새로운 방법을 구현해야 하기 때문에 SPI에 방법을 추가하는 것은 어렵다.인터페이스를 사용하여 SPI를 정의하는 경우, 제공자는 SPI 계약이 변경될 때마다 새로운 버전을 릴리스해야 한다.추상 클래스를 대신 사용할 경우 새로운 방법을 기존 추상 메소드의 관점에서 정의하거나 비어 있는 것으로 정의할 수 있다.throw not implemented exception
적어도 이전 버전의 서비스 구현을 컴파일하고 실행할 수 있는 스텁.
Java 8 및 기본 메서드에 대한 참고 사항
자바 8은 인터페이스와 추상 클래스 사이의 선을 더욱 흐리게 만드는 인터페이스에 기본 방법을 도입했지만, 이는 구현이 코드를 재사용할 수 있도록 하는 것이 아니라 API와 SPI(또는 추상 클래스 대신 SPI를 정의하는데 잘못 사용되는 인터페이스)를 쉽게 변경하기 위한 것이었다.
"책 지식"
OP의 답변에서 제공되는 기술적 세부사항은 "책 지식"으로 간주된다. 이는 보통 학교와 언어에 관한 대부분의 기술 서적에서 사용되는 접근방식이기 때문이다. 즉, 어떤 것이 무엇이며, 실제로 어떻게 사용하는가 하는 것이 아니라, 특히 대규모 애플리케이션에서 사용하는 것이기 때문이다.
여기 비유가 있다: 그 질문은 다음과 같다:
프롬나잇에 렌트하는게 더 좋은거야? 차랑 호텔방?
기술적인 대답은 다음과 같다.
글쎄, 차에서는 더 빨리 할 수 있지만, 호텔 방에서는 더 편하게 할 수 있어.반면에, 호텔 방은 한 장소에만 있는 반면, 차 안에서는 더 많은 곳에서 그것을 할 수 있다, 예를 들어, 멋진 경치를 위해 비스타 포인트에 갈 수 있다거나, 드라이브인 극장이나, 다른 많은 장소들, 또는 심지어 한 곳 이상에서도 할 수 있다.또한 호텔 방에는 샤워실이 있다.
그것은 모두 사실이지만, 완전히 다른 두 가지라는 점을 완전히 놓치고, 두 가지 모두 다른 목적에 동시에 사용할 수 있으며, 두 가지 옵션 중 어느 한 가지에 대해 '하는 것' 측면은 가장 중요한 것이 아니다.답은 원근법이 부족하고, 진정한 '사실'을 정확하게 제시하면서 철없는 사고방식을 보여준다.
인터페이스(interface)는 계약을 이행하는 등급이 방법의 이행을 약속하는 「계약」이다.수업 대신 인터페이스를 써야 했던 예로는 게임을 2D에서 3D로 업그레이드할 때였습니다.나는 2D와 3D 버전의 게임을 공유하기 위한 인터페이스를 만들어야 했다.
package adventure;
import java.awt.*;
public interface Playable {
public void playSound(String s);
public Image loadPicture(String s);
}
그러면 나는 아직 어떤 버전의 게임을 로딩하고 있는지 모르는 물체에서 그 방법들을 부를 수 있는 동시에 환경에 근거한 방법을 구현할 수 있다.
public class Adventure extends JFrame implements Playable
public class Dungeon3D extends SimpleApplication implements Playable
public class Main extends SimpleApplication implements AnimEventListener, ActionListener, Playable
전형적으로, 게임 세계에서, 세계는 게임에서 메소드를 수행하는 추상적인 클래스가 될 수 있다.
public abstract class World...
public Playable owner;
public Playable getOwner() {
return owner;
}
public void setOwner(Playable owner) {
this.owner = owner;
}
다음과 같은 식으로 생각해 보자.
- 클래스와 추상 클래스의 관계는 "is-a" 유형이다.
- 클래스와 인터페이스 사이의 관계는 "has-a" 유형이다.
그래서 당신이 추상적인 클래스의 포유류, 하위 클래스 휴먼, 그리고 인터페이스 Driving을 가지고 있을 때, 당신은 말할 수 있다.
- 각각의 인간은 포유동물이다.
- 각 인간에게는 운전(행동)이 있다.
나의 제안은 책 지식 구절은 그가 (여기서 이미 제안된 다른 사람들처럼) 양쪽의 의미적 차이를 듣고 싶었음을 나타내는 것이다.
추상계급은 순수 추상화가 아니다. 콘크리트(실행된 방법)의 집합은 물론 구현되지 않은 방법이다.그러나 인터페이스는 순수한 추상화다. 구체적인 방법이 아닌 구현되지 않은 방법만이 있기 때문이다.
왜 추상적인 수업인가?
- 사용자가 모든 객체에 대한 공통 기능을 쓰기를 원하는 경우.
- 추상 클래스는 최종 사용자에게 영향을 주지 않고 더 많은 기능을 추가하기 위해 향후 재구성을 위한 최선의 선택이다.
인터페이스가 필요한 이유
- 사용자가 개체에서 서로 다른 기능을 쓰려고 하는 경우.
- 인터페이스는 일단 인터페이스가 게시된 후 요구사항을 수정할 필요가 없다면 최선의 선택이다.
내가 관찰한 주요 차이점은 추상 클래스가 우리에게 이미 구현된 몇 가지 일반적인 행동을 제공하고 하위 클래스는 그것들에 해당하는 특정한 기능만 구현하면 된다는 것이었다.인터페이스에 관하여는 어떤 작업이 수행되어야 하는지만 명시하고 인터페이스에 의해 구현되지 않는다.나는 그것이 그 자체와 구현된 계층 사이의 계약을 명시한다고 말할 수 있다.
인터페이스는 일종의 효과를 가지고 있는 것으로 공개적으로 문서화되는 유전자의 집합과 같다: DNA 테스트는 내가 그것들을 가지고 있는지 여부를 내게 말해 줄 것이다 - 그리고 만약 내가 가지고 있다면, 나는 공개적으로 내가 "캐리어"라는 것을 알릴 수 있고 내 행동이나 상태의 일부는 그것들에 부합할 것이다. (물론, 나는 이 범위 밖의 특성을 제공하는 다른 많은 유전자들을 가지고 있을지도 모른다.)
추상계급은 단일성종의 죽은 조상(*):그녀는 살아날 수 없지만 살아 있는 (즉, 추세가 아닌) 후손은 그녀의 모든 유전자를 물려받는다.
(*) 이 은유를 늘리기 위해 모든 종의 구성원이 같은 연령을 산다고 하자.이것은 죽은 조상의 모든 조상들도 죽어야 한다는 것을 의미한다. 마찬가지로, 살아있는 조상의 모든 후손들도 살아 있어야 한다.
나는 일 때문에 면접을 보는데, 너의 답변도 기분 나쁘게 보일 것이다(미안하지만 나는 매우 정직하다.네가 차이에 대해 읽고 답을 수정한 것처럼 들리지만, 아마도 너는 그것을 실제로 사용해 본 적이 없을 것이다.
왜 각각을 사용하는지에 대한 좋은 설명은 차이에 대한 정확한 설명보다 훨씬 나을 수 있다.고용주들은 최후통첩을 통해 프로그램 진행자들이 자신들을 알지 못하는 일들을 하기를 원하는데, 이는 면접에서 입증하기 어려울 수 있다.개발자 역할이 아닌 기술 또는 문서 기반 작업에 지원할 경우 답변해 주셨습니다.
미래의 면접에서 행운을 빈다.
또한 이 질문에 대한 나의 대답은 네가 제공한 기술 자료보다는 면접 기술에 관한 것이다.아마 그것에 대해 읽어보는 것을 고려해보라.아마존닷컴은 이런 종류의 일에 훌륭한 장소가 될 수 있다.
몇 마디로 이렇게 대답할 것이다.
- 클래스 계층 구조를 통한 상속은 상태 상속을 의미한다.
- 인터페이스를 통한 상속은 행위 상속을 의미한다.
추상 클래스는 이 두 경우 사이의 것으로 취급될 수 있다(일부 상태를 도입하지만 행동을 정의할 의무도 있다), 완전 추상 클래스는 인터페이스(이것은 내가 그 구문을 알고 있는 한 C++에서만 가상의 방법으로 구성되는 클래스의 추가 발전이다).
물론 자바 8부터 조금씩 달라졌지만 생각은 그대로다.
컴파일러 팀과 인터뷰를 하고 있지 않다면 일반적인 자바 면접을 보기엔 이 정도면 충분할 것 같다.
인터페이스는 순전히 추상적이다. 인터페이스에 구현 코드가 없다.
추상계급은 방법과 그 구현을 모두 포함한다.
인터페이스 및 추상 클래스에 대한 튜토리얼을 보려면 여기를 클릭하십시오.
나조차도 여러 번의 면접에서 같은 질문에 직면했고, 면접관을 설득하는 것은 당신의 시간을 비참하게 만든다고 믿어.만약 내가 위의 모든 답을 가지고 있다면, 나는 그것을 더 설득력 있게 그리고 최선을 다해서 OO를 활용할 수 있도록 하나의 핵심점을 더 추가해야 한다.
규칙에 수정을 계획하지 않는 경우, 하위 클래스를 따르려면 오랫동안 인터페이스를 사용해야 하며, 수정할 수 없는 경우 다른 모든 하위 클래스의 변경 사항을 적용해야 하지만, 기능을 재사용하고 규칙을 설정하고 f를 열 수 있도록 해야 한다.또는 수정, 추상 클래스로 이동하십시오.
이런 식으로 생각해봐, 당신은 소모품 서비스를 이용했거나 코드를 세상에 제공했고 당신은 무언가를 수정할 기회가 있다고 가정해봐, 보안 검사를 해 봐. 그리고 만약 내가 코드를 소비하고 있고 업데이트한 어느 날 아침, 나는 내 Eclipse에 있는 모든 읽기 마크를 발견하면, 모든 어플리케이션이 다운돼.따라서 이러한 악몽을 방지하려면 인터페이스를 통한 추상화를 사용하십시오.
면접관을 어느 정도 납득시킬 수 있을 것 같은데...면접을 앞두고 행복한 시간 보내세요.
내가 밀접하게 연관된 두 계급 간의 행동을 공유하려고 할 때, 나는 공통적인 행동을 유지하고 두 계급의 부모 역할을 하는 추상적인 수업을 만든다.
내가 유형을 정의하려고 할 때, 내 개체의 사용자가 신뢰할 수 있는 방법으로 호출할 수 있는 방법 목록, 그리고 나는 인터페이스를 만든다.
예를 들어 추상적인 수업은 행동을 공유하는 것에 관한 것이기 때문에 나는 결코 구체적인 1개의 하위 클래스로 추상적인 수업을 만들지 않을 것이다.그러나 나는 단 하나의 구현만으로 인터페이스를 만들 수 있을 것이다.내 코드의 사용자는 구현이 단 한 가지뿐이라는 것을 모를 것이다.실제로 향후 릴리스에서는 여러 가지 구현이 있을 수 있는데, 모두 내가 인터페이스를 만들 때 존재하지도 않았던 새로운 추상 클래스의 하위 클래스들이다.
그것도 좀 너무 책략적으로 보였을지도 모른다(내가 기억하는 그 어디에도 그렇게 놓여 있는 것을 본 적이 없다.인터뷰 진행자(또는 OP)가 정말로 그 일에 대한 나의 개인적인 경험을 더 원했다면, 나는 인터페이스가 필요 없이 진화해 왔다는 일화를 준비했을 것이고, 그 반대의 경우도 마찬가지였을 것이다.
한 가지 더.이제 자바 8은 인터페이스에 기본 코드를 넣을 수 있게 되어 인터페이스와 추상 클래스 사이의 선을 더욱 흐리게 한다.하지만 내가 본 바로는, 그 기능은 자바 핵심 도서관의 제작자들에 의해서도 남용되고 있다.이 기능은 이항 비호환성을 생성하지 않고 인터페이스를 확장할 수 있도록 추가되었으며, 바로 그렇다.그러나 인터페이스를 정의하여 새로운 유형을 만드는 경우 인터페이스는 인터페이스에 불과해야 한다.공통 코드도 제공하려면 반드시 도우미 클래스(추상 또는 콘크리트)를 만드십시오.변경하고자 하는 기능으로 처음부터 인터페이스를 복잡하게 만들지 마십시오.
다중 상속에서 다이아몬드 문제를 방지하려면 Java에서 인터페이스를 선택하십시오.
모든 방법을 클라이언트에 의해 구현하려면 인터페이스를 사용하십시오.그것은 당신이 전체 응용프로그램을 추상적으로 설계한다는 것을 의미한다.
만약 당신이 이미 공통점을 알고 있다면 당신은 추상적인 수업을 선택한다.예: 추상 클래스 가져오기Car
더 높은 레벨에서 당신은 다음과 같은 일반적인 자동차 방법을 실행한다.calculateRPM()
그것은 일반적인 방법이고 당신은 고객이 그의 행동을 다음과 같이 실행하도록 한다.
calculateMaxSpeed()
아마도 당신은 당신의 일상 업무에서 마주친 몇 가지 실시간 예를 제시함으로써 설명했을 것이다.
인터페이스와 추상 클래스의 기본적인 차이는 인터페이스는 다중 상속을 지원하지만 추상 클래스는 지원하지 않는다는 것이다.
추상 클래스에서 당신은 인터페이스와 같은 모든 추상적인 방법을 제공할 수 있다.
왜 추상적인 수업이 필요한가?
일부 시나리오에서는 사용자 요청을 처리하는 동안 추상 클래스는 사용자의 의도를 알지 못한다.그 시나리오에서 우리는 클래스에 하나의 추상적인 방법을 정의하고 이 클래스를 확장하는 사용자에게 물을 것이다. 추상적인 방법으로 당신의 의도를 제공하라.이 경우에 추상적인 수업은 매우 유용하다.
인터페이스가 필요한 이유
예를 들어, 나는 그 분야에서 경험이 없는 일이 있다.예를 들어, 만약 당신이 건물이나 댐을 건설하고 싶다면, 당신은 그 시나리오에서 무엇을 할 것인가?
- 당신은 당신의 요구사항이 무엇인지를 확인하고 그 요구사항과 계약을 맺을 것이다.
- 그런 다음 Tenders에 연락하여 프로젝트를 생성하십시오.
- 누가 그 프로젝트를 만들었는지는 당신의 요구 사항을 충족시킬 것이다.그러나 건설 논리는 벤더마다 다르다.
여기서 나는 그들이 어떻게 구성되었는가에 대해 신경 쓰지 않는다.최종 목표는 나의 요구 사항을 충족시키든 아니든, 그것은 나의 핵심 사항일 뿐이다.
여기서 인터페이스라고 불리는 당신의 요구사항과 생성자는 구현자라고 불린다.
음, 지금 사람들은 배고픈 현실적 접근방식이지만, 대부분의 인터뷰 진행자들은 그들의 현재 요구대로 보이고 실용적인 접근을 원한다.
답변을 마친 후 다음 예제에 참여하십시오.
추상적:
예를 들어, 우리는 모든 직원에게 공통적인 파라메타를 가지고 있는 급여기능을 가지고 있다.그러면 우리는 CTC라는 추상적인 수업을 편파적으로 정의한 방법으로 할 수 있고, 그것은 모든 종류의 직원들에 의해 확장될 것이고, 그들의 여분의 비트에 따라 다시 만들어질 것이다.흔한 장난을 위해서.
public abstract class CTC {
public int salary(int hra, int da, int extra)
{
int total;
total = hra+da+extra;
//incentive for specific performing employee
//total = hra+da+extra+incentive;
return total;
}
}
class Manger extends CTC
{
}
class CEO extends CTC
{
}
class Developer extends CTC
{
}
인터페이스
자바에서 인터페이스는 인터페이스 기능을 확장하지 않고도 인터페이스 기능을 가질 수 있도록 허용하며, 당신은 당신의 어플리케이션에서 도입하고자 하는 기능의 서명의 구현을 명확히 해야 한다.그것은 당신에게 확실한 것을 강요할 것이다.다른 기능.
public interface EmployeType {
public String typeOfEmployee();
}
class ContarctOne implements EmployeType
{
@Override
public String typeOfEmployee() {
return "contract";
}
}
class PermanentOne implements EmployeType
{
@Override
public String typeOfEmployee() {
return "permanent";
}
}
당신은 추상적인 것으로 정의된 메토에 의해서도 추상적인 클래스로 그러한 강제적인 활동을 할 수 있다. 이제 클래스 tha는 추상적인 클래스의 기억을 그 추상적인 함수를 재정의할 때까지 확장한다.
인터뷰에 응할 수 있는 간단하고 합리적인 답변을 하기 위해 다음과 같이 제안한다.
인터페이스는 인터페이스가 되는 관계인 관련 클래스 패밀리의 API를 지정하는 데 사용된다.일반적으로 여러 구현이 있는 상황에서 구성 또는 런타임에 올바른 구현을 선택한다.(Spring을 사용하지 않는 한, 인터페이스는 기본적으로 Spring Bean이다.)인터페이스는 여러 상속 문제를 해결하기 위해 자주 사용된다.
추상계급이란 유산을 위해 특별히 고안된 계급을 말한다.이것은 또한 모든 구현이 (추상적인 클래스에서 발견되는) 어떤 공통성을 가지고 있는 다중 구현을 의미한다.
만약 여러분이 그것을 성공시키고 싶다면, 추상적인 수업은 종종 인터페이스의 일부를 구현한다고 말하라 - 일은 여러분의 것이다!
내가 이해한 바로는, 구현되지 않은 최종 변수와 방법으로 구성된 인터페이스는 서로 관련 있는 방법이나 방법의 그룹을 얻기 위해 클래스에 의해 구현된다.한편, 구현과 함께 비최종 변수와 방법을 포함할 수 있는 추상 클래스는 대개 가이드나 모든 관련 또는 유사한 클래스가 계승되는 슈퍼 클래스로 사용된다.즉 추상 클래스는 모든 하위 클래스가 공유하는 모든 방법/변수를 포함한다.
추상 클래스에서는 메서드의 기본 구현을 작성할 수 있다!그러나 인터페이스에서는 할 수 없다.기본적으로 인터페이스에는 인터페이스를 구현하는 클래스에 의해 구현되어야 하는 순수한 가상 방법이 존재한다.
그래, 네 대답은 기술적으로 정확했지만, 네가 틀렸던 부분은 네가 다른 것 보다 하나를 선택하는 것의 장단점을 이해한다는 것을 보여주지 않았어.또한 향후 코드베이스와 업그레이드의 호환성에 대해 우려하거나 우려했을 수 있다.이러한 유형의 대응이 도움이 되었을 수 있다(당신이 말한 것 외에):
"인터페이스 클래스를 통해 추상 클래스를 선택하는 것은 코드의 미래를 예측하는 것에 달려 있다.
추상 클래스는 기존 코드를 끊지 않고 앞으로도 계속 추상 클래스에 동작을 추가할 수 있기 때문에 더 나은 정방향 호환성을 허용한다. -> 인터페이스 클래스에서는 이것이 불가능하다.
반면에 인터페이스 클래스는 추상 클래스보다 유연하다.여러 인터페이스를 구현할 수 있기 때문이다.문제는 Java가 여러 개의 상속을 가지고 있지 않기 때문에 추상 클래스를 사용하면 다른 클래스 계층 구조를 사용할 수 없다는 것이다.
따라서, 결국 좋은 일반적 경험 법칙은 다음과 같다: 코드베이스에 기존/기본 구현이 없을 때 인터페이스 클래스를 사용하는 것을 선호한다.그리고 나중에 클래스를 업데이트할 것을 알고 있다면 추상 클래스를 사용하여 호환성을 유지하십시오."
다음 면접에서 행운을 빌어!
현실적인 시나리오로 답해 둘의 차별성을 보여주도록 노력하겠다.
인터페이스는 제로 페이로드로 제공된다. 즉, 어떤 상태도 유지될 필요가 없으므로 계약(능력)을 클래스에 연결시키는 것이 더 나은 선택이다.
예를 들어, 작업을 수행하는 작업 클래스가 있다고 가정해 보십시오. 이제 별도의 스레드에서 작업을 실행하기 위해 실제로 스레드 클래스를 확장할 필요는 없습니다만 작업에서 실행 가능한 인터페이스(즉, 실행() 방법을 구현)를 구현한 다음 이 작업 클래스의 개체를 스레드 인스턴스로 전달하고 시작() 방법을 호출하십시오.
이제 Runnable이 추상적인 수업이었는지 물어 볼 수 있겠니?
기술적으로는 가능했지만 설계상 현명한 선택이었을 겁니다.
- Runnable에는 연결된 상태가 없으며 Runnable() 방법에 대한 기본 구현을 '오퍼'하지 않는다.
- 다른 클래스를 확장할 수 없도록 작업 범위를 확장해야 함
- 태스크는 실행 가능 클래스에 대한 전문화로서 제공할 것이 없으며, 실행() 방법을 재정의하기만 하면 된다.
즉, 작업 클래스는 스레드가 될 스레드 클래스를 확장하는 Runnable 인터페이스 구문을 구현하여 달성한 스레드에서 실행할 수 있는 기능이 필요했다.
기능(계약)을 정의하기 위한 인터페이스를 제공하는 동시에 추상 클래스를 사용하여 기능의 스켈레톤(공통/부분) 구현을 정의하십시오.
고지 사항: 어리석은 예가 뒤따른다. 판단하지 않도록 노력하라:-P
interface Forgiver {
void forgive();
}
abstract class GodLike implements Forgiver {
abstract void forget();
final void forgive() {
forget();
}
}
이제 당신은 GodLike가 될 수 있는 선택권이 주어졌지만 Foraur만이 될 수 있다(즉, GodLike가 아닌)
class HumanLike implements Forgiver {
void forgive() {
// forgive but remember
}
}
또는 GodLike가 되어 다음과 같이 할 수 있다.
class AngelLike extends GodLike {
void forget() {
// forget to forgive
}
}
Java 8 인터페이스가 있는 P.S는 또한 정적인 기본 방식(과다한 구현)을 가질 수 있기 때문에 차이 b/w 인터페이스와 추상 클래스는 더욱 좁혀진다.
거의 모든 것이 이미 여기서 다뤄진 것 같다.실제 구현에 대해 1점만 더 추가abstract
클래스:
abstract
키워드는 또한 클래스가 인스턴스화되는 것을 막는데 사용된다.인스턴스화되지 않는 구체적인 클래스가 있는 경우 - 즉석화하십시오.abstract
.
내가 이해하고 접근하는 방법으로는
인터페이스는 규격/계약과 같으며, 인터페이스 클래스를 구현하는 모든 클래스는 추상 클래스에 정의된 모든 방법을 구현해야 한다(Java 8에서 소개된 기본 방법 제외)
클래스의 일부 방법과 일부 방법에 필요한 구현을 알 때 클래스를 추상적으로 정의하지만, 구현이 아닌 기능 서명은 알 수 없다.나는 나중에 이러한 방법들이 어떻게 구현되어야 하는지를 알게 되면 이 추상적인 계층을 확장하고 이러한 방법들을 구현할 수 있도록 이것을 한다.
참고: 인터페이스 방법의 기능 본체는 방법이 정적이거나 기본이 아니면 가질 수 없다.
여기 Java 8을 중심으로 한 설명이 있는데, 추상적인 클래스와 인터페이스 사이의 주요 차이를 보여주고 자바 어소시에 필요한 모든 세부사항을 다루려고 한다.
주요 개념:
- A수업 깡통
extend
단 한 학급이지만, 그것은 할 수 있다.implement
임의의 수의 인터페이스 - 인터페이스는 클래스를 정의하고 추상 클래스는 클래스를 정의하며
- 추상 수업은 수업이다.그것들은 인스턴스화 될 수는 없지만, 그렇지 않으면 일반 클래스처럼 행동한다.
- 둘 다 추상적인 방법과 정적 방법을 가질 수 있다.
- 인터페이스는 기본 방법과 정적 최종 상수를 가질 수 있으며, 다른 인터페이스를 확장할 수 있다.
- 모든 인터페이스 구성원은 공용(Java 9시까지)
인터페이스는 클래스를 정의하고 추상 클래스는 클래스를 정의하며
인터페이스는 종종 중심 정체성이 아닌 클래스의 능력을 설명하는데 사용된다. 예를 들어 자동차 클래스는 관련 없는 많은 물체에 적용될 수 있는 재활용 가능한 인터페이스를 구현할 수 있다.추상적인 계급은 그 후손들의 핵심 정체성을 규정한다.만약 당신이 Dog 추상적인 클래스를 정의한다면, 달마시안 후손들은 Dogs일 뿐, 그들은 단지 Dogable이 아니다.
자바 8, @Daniel Lerps의 대답은 인터페이스가 구현 클래스가 이행해야 하는 계약과 같다는 것이었다.
이제, 디폴트 방식으로는, 그들은 여전히 계약을 강제하는 믹신에 가깝지만, 또한 그 일을 하기 위해 코드를 부여할 수 있다.이것은 인터페이스가 추상 클래스의 사용 사례의 일부를 대신할 수 있게 했다.
추상 클래스의 요점은 추상적인 방법의 형태로 기능성이 결여되어 있다는 것이다.클래스에 추상적인 동작(다른 유형 간에 변경)이 없으면 대신 구체적인 클래스가 될 수 있다.
추상 수업은 수업이다.
다음은 추상 클래스에서 사용할 수 있지만 인터페이스에서는 사용할 수 없는 클래스의 몇 가지 일반적인 특성이다.
- 인스턴스(instance) 변수 / 최종 변수.따라서…
- 개체 상태를 액세스하고 수정할 수 있는 방법
- 개인/보호된 구성원(Java 9의 참고 사항 참조)
- 추상 또는 구체적인 클래스를 확장할 수 있는 기능
- 시공자
추상 클래스에 대해 유의할 사항:
- 그들은 그럴 수 없다.
final
(전체 목적은 확장되기 때문에) - 다른 추상 클래스를 확장하는 추상 클래스는 모든 추상 메서드를 자신의 추상 메서드로 상속한다.
추상적 방법
추상 클래스와 인터페이스 모두 0에서 많은 추상적 방법을 가질 수 있다.추상 메서드:
- 본문이 없는 메서드 서명(즉, no)
{}
) - 반드시 다음과 같이 표시되어야 한다.
abstract
추상 수업의 키워드인터페이스에서 이 키워드는 불필요하다. - 할 수 없다
private
(다른 세분류에 의해 구현되어야 하기 때문에) - 할 수 없다
final
(아직 시체가 없기 때문에) - 할 수 없다
static
(이유 때문에)
또한 다음 사항에 유의하십시오.
- 추상적인 방법은 동일한 클래스/인터페이스에서 추상적이지 않은 방법으로 호출할 수 있다.
- 추상 클래스를 확장하거나 인터페이스를 구현하는 첫 번째 콘크리트 클래스는 모든 추상적 방법에 대한 구현을 제공해야 한다.
정적 방법
추상 클래스의 정적 메서드는 다음과 같이 직접 호출할 수 있다.MyAbstractClass.method();
(즉, 일반계급과 마찬가지로 추상계급을 확장하는 계급을 통해서도 호출할 수 있다.)
인터페이스는 정적 방법을 가질 수도 있다.이러한 것들은 인터페이스의 이름을 통해서만 호출될 수 있다.MyInterface.method();
). 다음 방법:
- 할 수 없다
abstract
, 즉, 신체가 있어야 한다(위의 '이유' 참조) - 아니다
default
(아래 참조)
기본 방법
인터페이스는 다음과 같은 기본 방법을 가질 수 있다.default
키워드와 메서드 본문.이들은 다른 인터페이스 방법만 참조할 수 있으며(특정 구현의 상태를 참조할 수 없다).다음 방법:
- 아니다
static
- 아니다
abstract
(그들은 몸을 가지고 있다) - 할 수 없다
final
("기본값"이라는 이름은 재정의될 수 있음을 나타냄)
클래스가 동일한 서명으로 기본 메서드를 사용하여 두 개의 인터페이스를 구현하면 컴파일 오류가 발생하며, 이는 메서드를 재정의하여 해결할 수 있다.
인터페이스에는 정적 최종 상수가 있을 수 있음
인터페이스는 위에서 설명한 방법 유형 또는 상수만 포함할 수 있다.
상수는 다음과 같이 가정한다.static
그리고final
, 그리고 인터페이스를 구현하는 클래스에서 자격 없이 사용될 수 있다.
모든 인터페이스 구성원이 공용임
Java 8에서 인터페이스(및 인터페이스 자체)의 모든 멤버는public
, 그리고 있을 수 없다.protected
또는private
(그러나 Java 9는 인터페이스에서 개인 메서드를 허용한다.)
즉, 인터페이스를 구현하는 클래스는 공개 가시성을 가진 방법을 정의해야 한다(낮은 가시성으로는 방법을 재정의할 수 없다는 일반적인 규칙에 따름).
나는 면접관이 하고자 했던 것이 아마도 인터페이스와 구현의 차이였다고 믿는다.
Java 인터페이스가 아니라 좀 더 일반적인 용어로 "인터페이스"인 인터페이스는 기본적으로 인터페이스를 사용하는 클라이언트 코드로 이루어진 계약이다.
코드 모듈의 구현은 모듈을 작동하게 하는 내부 코드다.종종 당신은 둘 이상의 다른 방법으로 특정 인터페이스를 구현할 수 있고, 심지어 클라이언트 코드 없이도 구현을 변경할 수 있다.
Java 인터페이스는 어떤 구현도 명시하지 않고 클래스를 사용하는 클라이언트 코드의 이익을 위해 클래스가 어떻게 동작하는지를 정의하기 위해 위의 일반적인 의미에서 인터페이스로만 사용되어야 한다.따라서 인터페이스는 클라이언트 코드로 호출될 것으로 예상되는 방법에 대해 메서드 시그니처(이름, 반환 유형 및 인수 목록)를 포함하며, 원칙적으로 그 방법이 하는 일을 설명하는 각 방법에 대해 충분한 자바독을 가져야 한다.인터페이스를 사용하는 가장 강력한 이유는 인터페이스의 여러 가지 다른 구현을 계획하는 경우, 배포 구성에 따라 구현을 선택하는 경우일 수 있다.
대조적으로 Java 추상 클래스는 인터페이스를 지정하는 주된 목적이 아니라 클래스의 부분적인 구현을 제공한다.복수의 클래스가 코드를 공유할 때 사용해야 하지만, 하위 클래스도 구현의 일부를 제공할 것으로 예상될 때 사용해야 한다.이를 통해 공유 코드는 추상적인 클래스인 한 곳에만 나타날 수 있는 동시에 구현의 일부가 추상적인 클래스에 존재하지 않으며 하위 클래스에 의해 제공될 것으로 기대된다는 점을 명확히 할 수 있다.
'programing' 카테고리의 다른 글
Axios를 사용하여 객체를 JSon으로 게시 (0) | 2022.05.06 |
---|---|
Java에서 목록을 배열로 변환 (0) | 2022.05.06 |
Nuxt.js의 중첩된 경로에 선택적 파라미터를 생성하는 방법? (0) | 2022.05.06 |
공유 호스팅 환경에서 vue 앱을 배포하는 방법? (0) | 2022.05.06 |
변수가 C에서 특정 유형(두 유형을 비교)인지 확인하는 방법 (0) | 2022.05.06 |