方法与面向对象复习#
对应笔记:方法(函数)、类与对象(预习)、类与对象基础、继承、虚方法、抽象类、接口、静态成员、结构体与枚举 建议用时:70 分钟。
一、选择题#
1. ref 与 out 参数的区别是?
- A. 没有区别
- B. ref 传入前必须赋值,out 传入前不用赋值
- C. out 传入前必须赋值,ref 不用
- D. ref 只能用于值类型
答案
B。ref:传入前必须赋值(双向);out:传入前不用赋值,但方法内必须赋值(单向输出)。两者都能传出多个值,弥补 return 只能返回一个的限制。
2. 方法重载(Overload)的正确条件是?
- A. 方法名相同、返回值不同
- B. 方法名相同、参数列表不同(个数/类型)
- C. 方法名不同、参数相同
- D. 只要返回值不同就算重载
答案
B。重载要求:方法名相同 + 参数列表不同(参数个数或类型不同)。仅返回值不同不算重载,会编译错误。
3. 下列哪个修饰符表示"只有当前类内部可访问"?
- A. public
- B. internal
- C. private
- D. protected
答案
C. private。public 全部可访问;internal 当前项目;protected 当前类及子类;protected internal 当前项目 + 其他项目子类。
4. 子类继承父类后,下列说法正确的是?
- A. 可以继承父类所有 private 成员
- B. 可以继承父类 public / protected 成员
- C. 一个类可以继承多个父类
- D. 子类不能增加新成员
答案
B。C# 单继承——一个类只能继承一个父类;private 成员不能被子类访问;子类可以扩展新成员。
5. 抽象类(abstract)与接口(interface)的区别,错误的是?
- A. 抽象类可以有字段和普通方法
- B. 接口只能有方法签名和属性(无实现)
- C. 一个类可以实现多个接口
- D. 抽象类可以实例化(new)
答案
D。抽象类不能实例化,只能被继承。抽象类可有实现和字段;接口纯规范,可实现多个。
6. static 静态成员的特点,错误的是?
- A. 通过
类名.成员访问 - B. 所有对象共享一份
- C. 静态方法可以访问实例成员
- D. 生命周期从类加载到程序结束
答案
C。静态方法不能直接访问非静态(实例)成员,因为没有 this 引用;静态成员属于类,所有对象共享。
7. 虚方法(virtual)与抽象方法(abstract)的区别?
- A. 没有区别
- B. 虚方法有默认实现,抽象方法没有实现
- C. 抽象方法有默认实现
- D. 虚方法只能在抽象类中
答案
B。虚方法有默认实现、子类可选重写;抽象方法无实现、子类必须 override,且只能在抽象类中声明。
二、填空题#
1. 面向对象三大特性:==_== ==== ==_== ====、==_== ==== ==_== ====、==_== ==== ==_== ====。
答案
封装、继承、多态。
2. 类的默认访问修饰符是 ==_== ==== ==_== ====,类成员的默认修饰符是 ==_== ==== ==_== ====。
答案
internal(当前项目);private(类内)。
3. 子类构造函数执行顺序:先执行 ==_== ==== ==_== ==== 的构造函数,再执行 ==_== ==== ==_== ==== 的构造函数。
答案
父类(基类);子类(派生类)。多层继承时从最顶层基类逐层向下。
4. 构造函数链式调用使用 ==_== ==== ==_== ==== 关键字调用本类其他构造函数,用 ==_== ==== ==_== ==== 关键字调用父类构造函数。
答案
this(...);base(...)。两者不能同时使用。
5. const 是 ==_== ==== ==_== ==== 时确定值,readonly 是 ==_== ==== ==_== ==== 时确定值。
答案
编译时(声明时必须初始化);运行时(声明时或构造函数中初始化)。
6. 结构体是 ==_== ==== ==_== ==== 类型(值/引用),类是 ==_== ==== ==_== ==== 类型。
答案
值类型(struct);引用类型(class)。
三、代码分析题#
1. 阅读代码,写出输出结果。
class Animal
{
public virtual void Speak() { Console.WriteLine("动物叫"); }
}
class Dog : Animal
{
public override void Speak() { Console.WriteLine("汪汪汪"); }
}
Animal a = new Dog();
a.Speak();
答案
汪汪汪。父类引用指向子类对象时,调用虚方法会动态分派到子类重写版本(运行时多态)。
2. 阅读代码,写出执行顺序。
class A { public A() { Console.WriteLine("A"); } }
class B : A { public B() { Console.WriteLine("B"); } }
new B();
答案
先输出 A,再输出 B。创建子类实例时,先调用父类构造函数,再调用子类构造函数。
3. 下列代码哪里有问题?
答案
编译错误:仅返回值不同不算重载。两个方法名相同、参数列表相同,仅返回值不同,编译器无法区分。
4. 阅读代码,输出结果。
class Test
{
static int num = 0;
public void Add() { num++; }
public void Show() { Console.WriteLine(num); }
}
Test t1 = new Test();
Test t2 = new Test();
t1.Add(); t1.Add();
t2.Add();
t1.Show();
答案
3。num 是静态成员,所有对象共享同一份,t1 加 2 次、t2 加 1 次,共 3。
四、编程题#
1. 用继承实现:基类 Shape(抽象方法 Area),子类 Circle 和 Rectangle 实现面积计算。
答案
abstract class Shape
{
public abstract double Area();
}
class Circle : Shape
{
public double R { get; set; }
public override double Area() { return Math.PI * R * R; }
}
class Rectangle : Shape
{
public double W { get; set; }
public double H { get; set; }
public override double Area() { return W * H; }
}
2. 用方法重载实现:计算正方形、长方形、梯形的面积。
答案
3. 定义一个 Person 类(姓名、年龄、性别),用属性校验年龄必须在 0~150 之间。
答案
4. 用 ref/out 实现:一个方法同时返回两个数的和与差。
答案
5. 用接口实现:IUsb 接口(Read 方法),Mouse 和 Keyboard 类实现它。
答案
知识卡片#
面向对象三大特性?
封装(属性/访问修饰符控制访问)、继承(代码复用,单继承)、多态(虚方法 override 动态分派)。
ref 与 out 的区别?
ref 传入前必须赋值、双向;out 传入前不用赋值、方法内必须赋值、单向输出。都能一次传出多个值。
方法重载的条件?
同名 + 参数列表不同(个数/类型/顺序);仅返回值不同不算重载。
访问修饰符权限从大到小?
public > protected internal > internal > protected > private。
继承中构造函数的执行顺序?
先父类后子类;多层继承从顶层基类逐层向下。可用 base() 指定调用父类哪个构造函数。
抽象类 vs 接口?
抽象类可有实现/字段、单继承、子类 override;接口纯规范、多实现、成员无实现。
虚方法 vs 抽象方法?
虚方法有默认实现、可选重写;抽象方法无实现、必须重写、只能在抽象类中。
静态成员的特点?
属于类、所有对象共享、通过类名访问、静态方法不能访问实例成员。
struct 与 class 的区别?
struct 值类型(栈)、不能继承、无参构造受限;class 引用类型(堆)、可继承。
const 与 readonly?
const 编译时常量(声明时初始化、隐式 static);readonly 运行时常量(声明或构造函数中初始化、实例级)。