2013-08-02 1 views
1

이 질문은 this one과 비슷합니다. 차이점은 두 개의 기본 클래스를 갖고 싶다는 것입니다.C#에서 유창한 인터페이스와 다중 상속

예 :

public class Circle 
{ 
    private string _radius { get; set; } 

    public Circle Radius(string radius) 
    { 
     _radius = radius; 
     return this; 
    } 
} 

public class Box 
{ 
    private string _width { get; set; } 

    public Circle Width(string width) 
    { 
     _width = width; 
     return this; 
    } 
} 

public class CircleAndBox : Circle, Box // Can't do in c# 
{ 
    // should contain methods from both Circle and Box, but return CircleAndBox 
} 

아마 원과 상자는 좋은 예 아니었다. 기본적으로 다른 속성과 메서드를 가진 클래스를 나타냅니다. CircleAndBox 클래스는 Circle 및 Box와 동일한 속성 및 메서드를 가지고 있습니다. CircleAndBox에는 Circle이나 Box에 존재하지 않는 추가 속성과 메서드가있을 수 있습니다.

원하는 결과

내가 쓸 수 있어야 :

그것은 것
var circle = new Circle().Radius("5"); 
var box = new Box().Width("6"); 
var circleAndBox = new CircleAndBox().Radius("5").Width("6"); 

슈퍼 경우 :

내가 Circle 또는 Box 클래스에 메소드를 추가, I CircleAndBox 클래스를 만지지 않아야합니다. 그냥 하나의 클래스에서 일반 상속과 마찬가지로, CircleAndBox가 자동으로 모두 CircleBox

+1

인터페이스 인터페이스 인터페이스 ... 둘 모두에 대해 무엇이 필요합니까? 서클 + 상자 란 무엇입니까? 상자 안에 원이 있다면 원 반경이 상자 너비의 절반입니까? – Sayse

+0

'.Width ("6")'?? '.Width ("BigFat")'?? –

+0

'새 CircleAndBox(). 반경 ("5") 너비 ("6");'* 너무 유동적이기 때문에 의미가 무엇인지 이해하지 못합니다. – spender

답변

4

가 어느 클래스 CircleAndBox 상속을 가지고

IBox 및 ICircle을, 오히려 해당 클래스의 오브젝트를 참조하십시오. 각 클래스의 메소드를 다시 정의해야합니다. 암시 적 변환을 CircleBox에 추가하여 해당 개체에 대한 참조가 필요한 컨텍스트에서 사용할 수 있도록 할 수 있습니다. 암시 적 변환은 객체의 형태를 유지하지 않을 것이다, 그래서 하나가 Box을 복용하는 방법에 CircleAndBox를 전달하는 데이 기술을 사용하고 CircleAndBox로 반대편에 결과를 기대하지해야

public class CircleAndBox 
{ 
    public Circle Circle { get; private set; } 
    public Box Box { get; private set; } 

    public CircleAndBox() 
    { 
     Circle = new Circle(); 
     Box = new Box(); 
    } 

    public CircleAndBox Radius(string radius) 
    { 
     Circle.Radius(radius); 
     return this; 
    } 

    public CircleAndBox Width(string width) 
    { 
     Box.Width(width); 
     return this; 
    } 

    public static implicit operator Circle(CircleAndBox self) 
    { 
     return self == null ? null : self.Circle; 
    } 

    public static implicit operator Box(CircleAndBox self) 
    { 
     return self == null ? null : self.Box; 
    } 
} 

주 .

CircleAndBox cb = new CircleAndBox(); 

// Implicit conversion, b contains a Box object. 
Box b = cb; 

// Compile-time error CS0030. 
cb = (CircleAndBox)b; 
+0

질문의 업데이트 된 섹션 "다음과 같은 경우 :"를 참조하십시오. 나는 당신의 해결책이 그것을 다루지 않는다는 것을 이해합니다. – Dmitry

+0

@Dmitry C#에는 다중 상속이 없으므로 인터페이스를 독점적으로 사용하지 않고 런타임시 프록시 유형을 통해 위임 메소드를 자동으로 제공하지 않으면 사용자가 묻는 것은 불가능합니다. 스마트하게 들리는 – cdhowie

+0

:) 정말로, 나는 당신이 말한 것을 이해하지 못했습니다. 거기에 여전히 방법이 있다고 제안하고 있습니까?하지만 너무 복잡합니다. – Dmitry

1

사용 인터페이스의 모든 public 메소드 상속해야합니다

public interface IBox 
{ 
    Circle Width(string width) 
} 

public interface ICircle 
{ 
    Circle Radius(string radius) 
} 

public class Circle : ICircle 
{ 
    private int _radius { get; set; } 

    public Circle Radius(string radius) 
    { 
     _radius = radius; 
     return this; 
    } 
} 

public class Box : IBox 
{ 
    private int _width { get; set; } 

    public Circle Width(string width) 
    { 
     _width = width; 
     return this; 
    } 
} 

public class CircleAndBox : ICircle, IBox 
{ 
    // should contain methods from both Circle and Box, but return CircleAndBox 
} 
+0

'(string width)'는 여전히 나쁜 아이디어입니다. string은 크기를 나타내는 적절한 데이터 유형이 아닙니다. –

+0

그것은 단지 그들이 가지고있는 것으로부터 복사하여 붙여 넣기하는 것입니다. –

+0

이 방법이 마음에 들지 않는 이유는 CircleAndBox에있는 ICircle 및 IBox의 모든 메서드에 대한 구현을 작성해야한다는 것입니다. 이상적으로 나는 그것을 피하고 싶습니다. – Dmitry

0

나는 당신이 클래스의 다중 상속을 지원하지 않습니다 C#을 (그리고 일반적으로 닷넷) 이후 기대하고 정확하게 할 수 있다고 생각하지 않습니다. 하나의 클래스에서 상속 받아 인터페이스를 구현할 수 있습니다. 예를 들어

:

interface iBox 
{ 
    iBox Width(string width); //Assuming you want Box here and not Circle 
} 

이 그럼 당신은 상자

이제
class Box : iBox ... 

이 당신이 원하는 정확하게하지

public class CircleAndBox : Circle, iBox 
{ 
private Box _helper; 
public iBox Width(string width) { _helper.Width(width); return this; } 
} 

가질 수 있지만, 그것은 약이다 닫기는 C#으로 생각합니다. 약한 유형을 사용하고자한다면 각 메소드를 명시 적으로 구현하지 않고 _helper에 전달하는 위임 메소드가 있습니다.그러나 직접 위임을 사용하면 CircleAndBox 객체를 반환하지 않고 대신 _helper 객체를 반환합니다. 그 목적을 달성 할 수 있을지 확신 할 수 없습니다.

또한 상속하려는 클래스 중 적어도 하나를 제어하지 않으면이 기능이 작동하지 않습니다.

2

상속이란 "is a"를 의미합니다.

BallRoundThing입니다. CircleRoundThing입니다. BoxSquareThing입니다. LamborghiniCar이고 CarTransport입니다. BusBicycleTransport입니다.

"is a"관계가 아닌 경우 상속이 아닙니다. 그리고 이것이 C# 및 Java에서 다중 상속이 지원되지 않는 이유에 대한 설명이며, C++에서 알고있는 대부분의 사람들이 권장하지 않습니다. 한 물체는 한 번에 두 가지 일이 거의 없습니다.

단순히 코드 행을 저장하기 위해 상속을 오용하지 마십시오. 코드 줄을 저장하는 것이 합법적 인 목표 (동의하지 않음) 인 경우에도 필요하지 않습니다. 다른 두 가지 구조가 당신을 도울 수 있습니다.

먼저, 관계에 대해. 당신이 찾고있는 것은 완전히 다른 관계입니다. "a"는 아니지만 "as as as used". 그것이 인터페이스가 들어오는 곳입니다. 인터페이스는 객체를 사용할 수있는 것을 지정합니다. 따라서 두 개의 인터페이스 인 IBoxICircle을 가질 수 있습니다. 그러면 CircleAndBox 일은 두 인터페이스를 모두 구현할 수 있으므로 두 인터페이스로 모두 사용될 수 있습니다.

둘째로, 하나의 관계를 더 사용하여 더 쉽게 사용할 수 있습니다. 코드 줄을 저장하지 않습니다. 그러나 이 항상 CircleBox 클래스에 정의 된 적절한 동작을하는지 확인해야합니다. 이를 위해 위임 패턴과 함께 집계를 사용할 수 있습니다. 집계는 "가지고있다"는 관계입니다. CircleAndBox 클래스에 전용 Circle 개체와 전용 Box 개체가있는 경우 해당 개인 개체의 각 메서드/속성/이벤트를 호출하여 간단히 ICircleIBox 인터페이스를 구현 한 다음 반환 할 항목을 반환하십시오.

프레스토, 당신은 따라서 으로 사용할 수있는 실제로 동일한 방법 (위임)함으로써 이러한 노출에 작업을 전달하는 (집계) 원과 상자 인스턴스를 가지고 클래스 및이 (인터페이스) a 동그라미 을 상자로.

+0

코드 줄을 많이 저장하는 것에 신경 쓰지 않습니다. 나는 오히려 유지 보수에 관심이있다. 잘 써라! +1 – Dmitry