using System;
// 사각형 클래스
public class Rectangle
{
public double Width { get; set; }
public double Height { get; set; }
public double CalculateArea()
{
return Width * Height;
}
}
// 원 클래스
public class Circle
{
public double Radius { get; set; }
public double CalculateArea()
{
return Math.PI * Radius * Radius;
}
}
// 면적 계산기 클래스
public class AreaCalculator
{
public double CalculateRectangleArea(Rectangle rectangle)
{
return rectangle.CalculateArea();
}
public double CalculateCircleArea(Circle circle)
{
return circle.CalculateArea();
}
}
class Program
{
static void Main(string[] args)
{
Rectangle rectangle = new Rectangle { Width = 5, Height = 10 };
Circle circle = new Circle { Radius = 3 };
AreaCalculator calculator = new AreaCalculator();
double rectangleArea = calculator.CalculateRectangleArea(rectangle);
double circleArea = calculator.CalculateCircleArea(circle);
Console.WriteLine($"Rectangle Area: {rectangleArea}");
Console.WriteLine($"Circle Area: {circleArea}");
}
}
내 답:
새로 만들어질 Triangle에 접근할 방법이 현재로서 없기 때문에 불가능합니다.
모범 답:
불가능(가능은하지만 권장할 방법은 아님)
내 답:
위와 같은 코드는 새로운 클래스가 추가되거나 기존 클래스의 이름 등 요소가 변경 될 경우 그에 맞춰 새로운 코드를 추가하거나 변경해야 하기 때문에 유지보수 측면에서 어려움이 생깁니다.
모범 답:
예시 코드 중 CalculateArea 내부의 메서드들이 각 단일 클래스들을 매개변수로 받고있기 때문에 Triangle 클래스를 새로 만들고 면적 계산시 CalculateArea쪽에 메서드를 추가해야하는 필요성이 생기게 된다.
삼각형 면적 계산 방법중 유사한 방법이 사각형이기 때문에 사각형의 CalculateArea 메서드를 virtual로 바꾸고, Triangle : Rectangular 식으로 상속하게되면 가능은하지만 가독성이 떨어지기에 권장할 방법은 아니다.
만약 이 코드 자체를 리팩토링하게된다면 다음과 같이 작성할 수 있다.
interface IShape
{
double CalculateArea();
}
public class Rectangle : IShape
{
double width,height;
public double CalculateArea()
return width*height;
}
public class Circle : IShape
{
double radius;
public double CalculateArea()
return Math.PI * radius * radius;
}
public class Triangle : IShape
{
double width,height;
public double CalculateArea()
return 0.5*width*height;
}
public class Calculator
{
public double Calculate(IShape shape)
return shape.CalculateArea();
}
class Program
{
static void Main()
{
...
}
}
내 답:
단일 책임 원칙 - 각 클래스는 하나의 기능을 가지며, 그 클래스가 제공하는 기능은 그 하나의 기능에 대한 책임을 져야 한다는 원칙입니다.
개방 폐쇄 원칙 - 확장에는 열려있고, 변경에는 닫혀있어야 한다는 원칙입니다.
리스코프 치환 원칙 - 하위 타입은 상위 타입을 대체할 수 있어야 한다는 원칙입니다.
인터페이스 분리 원칙 - 클래스에 사용되지 않는 인터페이스를 구현하지 말아야 한다는 원칙입니다.
의존성 역전의 원칙 - 상위 클래스는 하위 클래스에 의존해서는 안 되며, 하위 클래스가 상위 클래스에 의존해야 한다는 원칙입니다.
모범 답:
- 다섯 개의 원칙을 차례로 언급하고, 간단하게 설명을 하면 충분합니다.
- 단일 책임 원칙 (SRP)
- 개방-폐쇄 원칙 (OCP)
- 리스코프 치환 원칙 (LSP)
- 인터페이스 분리 원칙 (ISP)
- 의존 역전 원칙 (DIP)
SOLID 원칙이란 객체지향 프로그래밍을 하면서 유지, 보수, 확장성을 향상시키는 방향으로 개발을 해 나가기를 권장하는 방법이다. 총 5가지의 원칙들의 집합으로 구성되어있고, 각각의 이니셜을 가져와서 SOLID라는 명칭을 가지게 되었다. 각각의 원칙들에 대해서 설명해보자면
내 답:
다형성이 잘 적용되면 동일한 이름의 메서드가 서로 다른 객체에 따라 다르게 동작 할 수 있기 때문에 코드의 재사용성이 올라간다는 장점이 있습니다.
모범 답:
- 다형성에 대한 설명과 함께, 구현 방법에 대해 인터페이스를 곁들여 이야기해주면 정말 좋습니다.
- 다형성의 장점은 코드 재사용, 유연성, 유지보수성에 대해 언급해주시면 좋습니다.
다형성 : 기존 코드의 재사용성과 유연성을 활용하여 다른 객체들을 생성할 수 있다는 개념
장점: 기존 코드의 수정을 최소화하며 새로운 클래스나 메서드들을 추가할 수 있다, 가독성을 높이며 의존성을 줄일 수 있다.
내 답:
override는 상위 클래스에 있는 메서드를 하위 클래스에서 새로운 코드를 덮어 씌우는 것 입니다.
overload는 같은 이름의 메서드가 매개변수를 어떻게 받느냐에 따라 분리되어 있는 형태입니다.
모범 답:
- override의 경우 상속에 있어 메서드 재정의라는 단어로 설명해주시면 좋습니다.
- 추가적으로 가상 함수에 대해 함수 테이블(Method Table) 또는 가상 테이블(Virtual Table)을 같이 언급하여 설명해주시면 좋습니다.
- overload의 경우 동일한 메서드 이름을 사용한다는 특징을 언급해주시는 것이 좋습니다. 다형성을 같이 언급하면 정말 좋습니다.
overload : 서로 다른 형, 인자를 받는 동일한 이름의 메서드를 정의할 때 주로 사용, 해당 클래스 내에서 클래스의 이름이 아닌 출력 자료형, 매개변수 종류에 따라 구분
override : 부모클래스에서 abstract나 virtual로 작성된 메서드들을 자식 클래스에서 재정의 할 때 사용되는 키워드, 기존 메서드 위에 올라탄다(ride)는 느낌으로 받아들이면 편함
내 답:
클래스 외부에서 클래스의 메서드처럼 사용할 수 있는 새로운 메서드를 만드는 기능입니다.
확장 클래스를 선언할 때 static으로 선언을 해줍니다.
확장 메서드를 만들 때도 static으로 선언을 해줍니다.
확장 메서드의 첫 번째 매개변수는 this 키워드를 사용한 후 확장하고자 하는 클래스 타입을 적어 줍니다.
모범 답:
- 코드 재사용과 유지보수성을 위해 기존 클래스의 메서드를 확장한다고 설명해주면 좋습니다.
- 사용법의 경우
this
키워드와 함께 설명해주세요.
확장 메서드: 기존 클래스(A라고 지칭)에서 정의되어있지 않지만 외부 클래스(B라고 지칭)에서 정의하여 마치 A클래스의 메서드처럼 사용할 수 있는 기법
큰 특징으로는 static을 활용한 클래스 접근이 다분하기에 자주 사용되는 기법은 아님
Array
클래스에 확장 메서드를 이용하여 배열의 평균값을 계산하는 기능을 추가하세요.
이 확장 메서드는 CalculateAverage
라는 이름을 가지며, int[]
타입의 배열을 입력으로 받아 평균값을 double
타입으로 반환해야 합니다.
using System;
namespace ArrayExtensions
{
public static class ArrayExtension
{
public static double CalculateAverage(this int[] array)
{
// TODO: 확장 메서드 CalculateAverage를 구현하세요
//int i = 0;
//foreach (int j in array)
//{
// i += j;
//}
//return i / array.Length;
double sum = 0;
for(int i = 0; i < array.Length; i++)
{
sum += array[i];
}
return sum / array.Length;
//
}
}
class Program
{
static void Main(string[] args)
{
int[] numbers = { 1, 2, 3, 4, 5 };
// 확장 메서드를 사용하여 배열의 평균값을 계산하고 출력
double average = numbers.CalculateAverage();
Console.WriteLine($"The average is: {average}");
}
}
}