Protected

public class Car
{

// member field
private bool disel;     // disel은 파생 클래스에서 사용하지 못함
protected bool gasoline;// gasoline은 파생 클래스에서 사용가능하나 클래스 외부에서는 호출하지 못함
protected int wheel = 4;// wheel은 파생 클래스에서 사용가능하나 클래스 외부에서는 호출하지 못함

// constructor
protected Car() { disel = true; gasoline = true;  }
protected Car(int wheel) { this.wheel = wheel; disel = false; gasoline = false; }

// method
public void Move()
{
if (disel)
Console.Write(“Car 디젤”);
else
Console.Write(“바퀴 {0} 자동차가 굴러간다.”, wheel);
}

}

public class Sedan : Car
{

// member field
private bool gasoline;  // 파생 클래스에서 기반클래스에 멤버필드명이 같다면 default는 자신의 멤버부터 호출 &
Sedan.gasoline은 Car.gasoline을 숨김 => private new bool gasoline와 같은 의미

// constructor
public Sedan() { gasoline = false;  }  // Sedan() : base() 호출
public Sedan(int wheel) : base(wheel) { gasoline = true; } // Sedan(int wheel) :
base(int wheel)를 호출 – protected 생성자는 기반 클래스의 생성자 호출 base에서 사용됨

// method
public void SedanMove()
{

// base의 gasoline과 this의 gasoline을 구분해야하는 경우
if (base.gasoline)
Console.Write(“Car가솔린”);
if (this.gasoline)
Console.Write(“Sedan 가솔린”);

Console.WriteLine(“바퀴 {0} 세단자동차가 굴러간다.”, wheel);

}

static void Main(string[] args)
{

// error CS1540: ‘Car’형식의 한정자를 통해 보호된 ‘Car.Car()’ 멤버에 액세스할 수 없습니다. 한정자는 ‘Sedan’ 형식이거나 여기에서 파생된 형식이어야 합니다.
//Car myCar = new Car();    // 기반 클래스 생성자 Car()는 상속되지 않음. 따라서 new를 이용하여 객체를 생성할 수 없음.
//myCar.Move();             //  myCar 객체없이 myCar.Move() 호출할 수 없음
//Console.WriteLine(“마이카의 바퀴는 {0}개 이다.”, myCar.wheel); // myCar 객체없이 myCar.wheel 호출할 수 없음

// 바퀴 4개 디젤 자동차
Sedan myCar1 = new Sedan();
myCar1.Move();       // Car를 상속받았기 때문에 Move() 메소드를 사용할 수 있음
myCar1.SedanMove();  // Sedan 자신의 메소드 사용가능
Console.WriteLine(“마이카의 바퀴는 {0}개 이다.”, myCar1.wheel); // 상속된 객체에서 기반 객체의 protected 멤버 필드 호출가능

Console.WriteLine();

// 바퀴 6개 가솔린 자동차
Sedan myCar2 = new Sedan(6);
myCar2.Move();       // Car를 상속받았기 때문에 Move() 메소드를 사용할 수 있음
myCar2.SedanMove();  // Sedan 자신의 메소드 사용가능
Console.WriteLine(“마이카의 바퀴는 {0}개 이다.”, myCar2.wheel); // 상속된 객체에서 기반 객체의 protected 멤버 필드 호출가능

}

}

C# constructor usage guideline

private constructor는 정적 메소드와 속성 (static method & property)만 있는 경우 사용함.
http://msdn.microsoft.com/en-us/library/vstudio/kcfb85a6.aspx

public class Counter
{
private Counter() { }
public static int currentCount;
public static int IncrementCount() {  return ++currentCount; }
}
class TestCounter
{
static void Main()
{
// If you uncomment the following statement, it will generate
// an error because the constructor is inaccessible:
// Counter aCounter = new Counter();   // Error
Counter.currentCount = 100;
Counter.IncrementCount();
Console.WriteLine(“New count: {0}”, Counter.currentCount);
// Keep the console window open in debug mode.
Console.WriteLine(“Press any key to exit.”);
Console.ReadKey();
}

} // Output: New count: 101

protected constructor는 추상클래스 (abstract class)에서 사용을 권고함. 추상 클래스를 상속받는 파생클래스에서 파생 클래스 생성자가 부모 클래스 즉, 추상 클래스를 초기화 하기 위해 추상 클래스 생성자를 호출 할 수 있도록 지원함.
http://msdn.microsoft.com/en-us/library/bcd5672a%28v=vs.80%29.aspx
http://msdn.microsoft.com/ko-kr/library/ms229047(v=vs.100).aspx

public abstract class Shape
{
protected Shape(string name) { this.name = name; }
private string name;
public virtual void Print() { Console.Write(this.name); }
}
public class Triangle: Shape
{
public Triangle(string name): base(name) { this.bottom = 1; this.height = 1 }
private double bottom, height;
public override void Print()
{
base.Print();
Console.WriteLine(” 밑변: {0} 높이: {1}”, this.bottom, this.height);
}
}
public class Rectangle: Shape
{
public Rectangle(string name): base(name) { this.width = 2; this.height = 3 }
private double width, height;
public override void Print()
{
base.Print();
Console.WriteLine(” 가로: {0} 세로: {1}”, this.width, this.height);
}
}
class ShapeTest
{
static void Main()
{
// Shape s = new Shape(“도형”);   // Error CS0144, Cannot create an instance of the abstract class
Shape s = new Triangle(“삼각형”);
s.Print(); // 삼각형 밑변: 1 높이: 1
s = new Rectangle(“직사각형”);
s.Print(); // 직사각형 가로: 2 세로: 3
}
}