2017-05-08 49 views
0

C# : 상속 및 추상 클래스 - 기본. 대 : 나는 다음과 같이 내 생성자를 설정하려고하면 "형식의 책 인수 '0 사용하는 생성자가 포함되어 있지 않습니다'을": (생성자 이니셜) 기본 I 오류를 받고 있어요

using System; 
using System.Collections.Generic; 
using System.IO; 
abstract class Book 
{ 

    protected String title; 
    protected String author; 

    public Book(String t,String a){ 
     title=t; 
     author=a; 
    } 
    public abstract void display(); 

} 

class MyBook : Book 
{ 
    private int price = 0; 

    public MyBook(string t, string a, int p) 
    { 
      base.title = t; 
      base.author = a; 
      this.price = p; 
    } 

    public override void display() 
    { 
     Console.WriteLine($"Title: {title}"); 
     Console.WriteLine($"Author: {author}"); 
     Console.WriteLine($"Price: {price}"); 
    } 
} 

나는 기본 키워드를 어떻게 사용하고 있는지에 대한 문제를 좁혔다. 기본 생성자 initializer를 생성자 선언에 base 키워드와 함께 사용해야합니다.

public MyBook(string t, string a, int p) 
    : base(t, a) 
    { 
      this.price = p; 
    } 

누군가 내가 왜 자료를 사용할 수 없는지 설명해 주시겠습니까? 여기 내 생성자에? 제목과 저자 변수가 둘 다 추상 클래스의 보호 된 멤버이기 때문입니까? 나는 Book에서 파생 된 이래로이 보호받는 멤버들에게 접근 할 수 있다고 생각했습니다. 아니면 하위 클래스를 인스턴스화하지 않았기 때문에 내 생성자를 이런 식으로 설정할 수 없기 때문입니까?

+1

같은 일에 대해 갈 것 같은 클래스 구조를 정의하세요. – vendettamit

답변

1

보호 속성을 원하는 방식으로 사용할 수 있습니다. 그것은 당신이 마주 치는 문제가 아닙니다. 파생 클래스의 인스턴스를 만들려고 할 때 프로그램은 개체의 해당 부분을 만들기 위해 호출 할 기본 클래스의 생성자를 알아야합니다. 지정하지 않으면 기본 (인수 없음) 생성자가 호출됩니다. 기본 클래스에는 그 중 하나가 없으므로 오류가 발생합니다. :base(t,a)은 사용할 생성자와 전달할 인수를 알려주는 데 필요합니다. 어리석은 것이 예에서는 물론

public MyBook(string t, string a, int p) 
: base(t, a) 
{ 
     base.title = t; 
     base.author = a; 
     this.price = p; 
} 

,하지만 당신은 당신이하려고했던 방법으로 이러한 속성을 사용하게됩니다 것을 볼 수있다 : 당신이 원하는 경우에, 당신은 할 수 있습니다.

+0

카일 감사합니다! 이제 이해가된다 – xslipstream

0

생성자를 호출하지 않고 기본 클래스의 속성을 설정할 수는 없습니다. 기본 클래스에는 기본 클래스의 생성자를 명시 적으로 호출해야하는 인수 및 기본 생성자가없는 생성자가 있으므로

public MyBook(string t, string a, int p) 
    :base(t, a) 
{ 
    this.price = p; 
} 

파생 클래스의 인스턴스를 만들면 실제로 기본 클래스의 인스턴스가 만들어집니다. 클래스에 인수가 필요한 생성자가 있고 에 기본 생성자가없는이 있으면 해당 생성자 중 하나를 호출하는 것이 유일한 방법입니다.

protected Book() { } 

을하지만 그렇게하지 그것은 더 나은 : BookMyBook가 동일한 어셈블리에 있었다

경우에 당신은 이런 식으로 만 상속 클래스를 호출 할 수있는 protected 기본 생성자를 추가 할 수 있습니다. 당신은 그 이유 때문에 생성자를 두었습니다. 그래서 생성자를 우회하는 것을 원하지 않습니다. 상속받은 클래스조차도 원하지 않습니다.

예를 들어 Book에 null title 또는 author을 사용할 수 없으므로 생성자에 유효성을 검사하여 null이 아닌지 확인할 수 있습니다. MyBook이 기본 클래스 생성자를 호출하는 것이 좋은 이유입니다. 이제 검증이 항상 수행되기 때문입니다.

+0

실제로 그는 할 수 있습니다. ctor 인수는 그가 놓친 언어 제약 일뿐입니다. – vendettamit

+0

그는 기본 클래스의 속성을 설정할 수 있습니다. 기본 클래스의 속성을 설정할 수는 없습니다. (그래, 내가 더 명확하게 할 수있어.) –

+0

글쎄, 네가 너에게 설명하게 만들었다. :) – vendettamit

1

생성자가없는 클래스를 작성하면 컴파일러는 간단한 quickie 클래스 작성의 편의를 위해 매개 변수없는 기본 생성자를 정의합니다.

명시 적으로 생성자를 정의하기 시작할 때 컴파일러는 사용자가 원하는 생성자 집합을 정확하게 정의한다고 가정합니다. 이렇게하면 기본 생성자를 사용하는 간단한 클래스를 작성하는 편의성을 유지하면서 클래스 작성 방법을 제어 할 수 있습니다.

MyBookBook입니다. MyBook이 초기화되기 전에 먼저 Book이 초기화되어야합니다. 그러나 여기서 호출 할 매개 변수없는 생성자는 없습니다. Book은 명시 적으로 컴파일러와 관련하여 을 선택하여 여기에서 수행중인을 금지합니다. 이 언어에서는 사람 (하위 클래스), 샐리 (Sally)의 아줌마, 누구든지 매개 변수없는 생성자를 사용하여 Book을 만들 수 있다고 가정합니다.

public MyBook(string t, string a, int p) 
{ 
     base.title = t; 
     base.author = a; 
     this.price = p; 
} 
+0

에드 감사합니다! 나는 지금 이해한다 – xslipstream

0

문제를 해결할 수있는 방법은 여러 가지가 있지만 나는 당신의 문제를 해결하는 대신 더 나은 디자인 관점에서 대답하려고 노력할 것이다.

당신이 그것을 초기화하고 당신에게 그것의 회원 서비스를 제공하기 전에이 개 인수를 예상하는 기본 생성자를 정의하기 때문에 나는이

using System; 
using System.Collections.Generic; 
using System.IO; 

abstract class Book 
{ 
    protected String title; 
    protected String author; 

    public Book(String t, String a) 
    { 
     this.title = t; 
     this.author = a; 
    } 

    public abstract void display(); 
} 

class MyBook : Book 
{ 
    private int price = 0; 

    public MyBook(string t, string a, int p) : base(t, a) // Let the base class decide what it wants to do with these arguments 
    { 
     this.price = p; 
    } 

    public override void display() 
    { 
     Console.WriteLine($"Title: {title}"); 
     Console.WriteLine($"Author: {author}"); 
     Console.WriteLine($"Price: {price}"); 
    } 
}