상속에 관련된 코드인데 이게 어떻게 가능한건가요?

안녕하세요. 최근에 코드를 리팩토링하면서

언어적으로 부족한 부분이 많아 C#을 다시 공부하고 있습니다

그러던 도중 이해가 안가는 코드가 있어 질문드립니다

<코드>

using System;
using System.Collections.Generic;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var temp = new ImplClassA
            {
                Values = new List<InterfaceB>
                {
                    new ImplClassB{ Value = "A" },
                    new ImplClassB{ Value = "B" },
                    new ImplClassB{ Value = "C" },
                    new ImplClassB{ Value = "D" },
                    new ImplClassB{ Value = "E" },
                }
            };
            DoSomething(temp);
        }

        public static void DoSomething(InterfaceA iParam)
        {
            foreach (var item in (iParam as ImplClassA).Values)
            {
                Console.WriteLine((item as ImplClassB).Value);
            }
        }
    }

    interface InterfaceA { }

    interface InterfaceB { }

    class ImplClassA : InterfaceA
    {
        public List<InterfaceB> Values { get; set; }
    }

    class ImplClassB : InterfaceB
    {
        public string Value { get; set; }
    }
}

ImplClassA, ImplClassB는 각각 InterfaceA, InterfaceB를 구현하지만

각 Interface에는 아무런 코드가 없고 구현되는 클래스에서만 프로퍼티가 있는 상황입니다.


Main 메소드에서 ImplClassA 인스턴스를 만들고 DoSomething 메소드에 인자값으로 넘겨주고 있습니다.
DoSomething 메소드에서 InterfaceA만을 매개변수로 받지만
ImplClassAInterfaceA를 상속하고 있으므로
형변환이 일어나서 ImplClassA를 매개변수로 받는데 문제가 없다는것까지는 이해를 했습니다.

하지만 다음코드부터 의문이 생깁니다.
InterfaceA를 다시 ImplClassA로 형변환을 하는데 InterfaceA내부에는 프로퍼티가 아무것도 없습니다.
이런 상황에서 매개변수로 받은 ImplClassA의 값들을 다시 사용할 수 있습니다.
InterfaceBImplClassB로 형변환한경우도 마찬가지구요…

보통의 인터페이스 예제들을 보면 인터페이스 내부에 프로퍼티를 정의해놓는 경우가 많아서
대충 이해를 했었는데 이러한 코드는 처음 봐서 이게 어떻게 가능한건지 답변주시면 감사하겠습니다.
추가로 용어가 이상한 부분이나 제가 잘못 이해하고 있는 부분 지적부탁드립니다.

좋아요 1

본문이 길어서 제가 파악한 핵심에 대한 답을 먼저 드려봅니다. 혹시 답변의 포인트가 맞지 않으면 다시 한 번 알려주시면 감사하겠습니다.

위의 코드에서 사실 iParam은 InterfaceA의 멤버를 탐색하는 것이 아니라 ImplClassA의 멤버를 탐색하고 있고, 그래서 코드가 잘 작동하게 됩니다. 말씀하신대로 (iParam as InterfaceA)로 고치면 코드가 작동하지 않을 것입니다.

좋아요 4

답변주셔서 감사합니다

업캐스팅에 대해 개념을 잘못 이해하고 있었습니다.

질문 제목도 인터페이스에서 상속으로 변경하였습니다

좋아요 2

제목을 바꾼다고하셔서 댓글 달지만…
이건 상속이 아니라 다형성 제공입니다.

상속은 class, abstract class 를 지정했을때 상속입니닷!

좋아요 2

'상속은 class, abstract class 를 지정했을때 상속’이라고 말씀하셨는데
상속받은 인터페이스를 통해 업캐스팅이 일어나는 경우의 예시여서 상속도 맞지 않나요?
혹시 제가 잘못 이해한 부분이 있을까요?

좋아요 1

제 말은…

// 아래는 상속입니다.
class AA : BB
{
}

// 아래는 상속이 아닙니다. 다형성 제공입니다.
class AA : IinterfaceAA
{
}

개체 지향 패러다임에서 상속은 기능을 물려 받아야 합니다.
또한 C#은 단일 상속만을 지원합니다. (여러 클래스로 동시에 상속 안됨)
즉, 인터페이스를 엄청나게 열거해도 그건 상속이 아닙니다.

또한 Up-casting, Down-casting은 상속 계보에서 다루어지는 내용입니다.

질문해주신 내용의 코드는 그냥 Casting입니다.
그것을 말로 풀어자면 …

ImplClassA에 다형성으로 InterfaceA를 작성하고, 인스턴스화된 ImplClassA를 InterfaceA로 캐스팅했다

일것 같습니다.

좋아요 6

아… 그렇군요
잘못 알고있는 개념에 대해 모르고 지나칠뻔 했네요
답변해주셔서 감사합니다

좋아요 3

아닙니다… 저도 닷넷데브를 통해 많이 배우고 있는걸요.

그리고… 7달 전이라뇨!
커뮤니티 많이 찾아주세요!

좋아요 2

동의 합니다.

이게 같은 기호를 사용해서 표현하기 때문에 혼란스러울 수 있는데
그래서 저는 클래스는 상속(혹은 파생)으로 부르고, 인터페이스는 계약(Contract)이라고 표현하는 편입니다.
개념적으로는 @SangHyeon.Kim 의 표현이 훨씬 더 정확한 것 같습니다.

좋아요 3