接口本身并不实现任何功能,它只是和声明实现该接口的对象订立一个必须实现哪些行为的契约。
这些契约,实现该接口的对象都要遵守,所以是全部方法.
而且 如果该接口 实现了其他接口,那么 这个对象 要实现 所有结构中的 所有方法.
我的理解是,对于定义了Dog派生类继承了Pet的情况,是Dog类的父类由Object变成了Pet,但仍可以通过继承Pet类得到Object类的相关属性和方法。
NICE!
不知道
输入的不是数字呗,转换异常
那个章节的?这个章节中老师那里没发现这个语句啊
引用类型存在堆上(需要垃圾回收介入),值类型存在栈上(不需要垃圾回收机制介入)
看一下报错提示,一般都能看到原因
visual studio c#
emm 查看电脑的杀毒软件 然后禁用它
我感觉你应该理解的是“泛”。瓶子和水,瓶子可以装你想要装的类型的水。
抱歉,,我没看完就发了,,原来后边有讲。。
一对一的意思,对数级的,应该是这样吧??
我在收看的教程视频是,把代码也给敲出来了,里面有相应的注释,分享一下吧
using System;
using System.Globalization;
using System.Net.Cache;
namespace PetShop
{
interface ICatchMice //基类中接口的定义
{
void ICatchMice();
}
interface IClimbTree //基类中接口的定义
{
void IClimbTree();
}
abstract public class Pet
{
public int _age;
public string _name;//设置为public或者protected,以便于子类访问
public Pet(string name)//构造一个方法
{
_name = name;
_age= 0;
}
public static Pet operator ++ (Pet pet)//重装运算符定义
{
++pet._age;
return pet;
}
public void PrintName()
{
Console.WriteLine("Pet's name is " + _name);
}
public void ShowAge()
{
Console.WriteLine(_name+"'s Age="+_age);
}
abstract public void Speak();
/*上面这句话 是抽象方法的应用例子,之前版本 虚方法:
virtual public void Speak()
{
Console.WriteLine(_name+"is speaking ");
}
*/
}
static class PetGuide
{
static public void HowToFeedDog(this Dog dog)
{
Console.WriteLine("Play a vedio about how to feed a dog");
}
static public void HowToFeedCat(this Cat cat)
{
Console.WriteLine("Play a vedio about how to feed a cat");
}
}
public class Dog:Pet //继承的应用
{
static int Num;//静态类的应用
static Dog()//静态构造方法的定义
{
Num = 0;
}
public Dog(string name):base(name)//显式调用基类构造函数
{
++Num;
}
new public void PrintName()//重定义函数,隐藏功能实例
{
Console.WriteLine("宠物的名字叫 " + _name);
}
//sealed public override void Speak()//重写抽象函数,用override在派生类中被继承,
//如果加上sealed关键字,那么在Dog的子类Hashiqi里重写Speak函数就会出错,sealed是密封的意思,不能被重写
public override void Speak()//重写抽象函数,用override在派生类中被继承
{
Console.WriteLine(_name + " is speaking"+":wowo");
}
static public void ShowNum()//静态构造方法的调用
{
Console.WriteLine("Dog's number:" + Num);
}
/*public static implicit operator Dog(Cat cat)//隐式转换的定义,目的在于把猫猫变成狗狗,
{
return new Dog(cat._name);
}*/
}
class Cat :Pet,ICatchMice, IClimbTree //子类中接口的调用
{
public Cat(string name) : base(name)
{
}
public override void Speak()
{
Console.WriteLine(_name + " is speaking" + ":mewo");
}
public void ICatchMice()//子类中接口的调用
{
Console.WriteLine(_name+"can catch mice");
}
public void IClimbTree()//子类中接口的调用
{
Console.WriteLine(_name+"can climb tree");
}
public static implicit operator Cat(Dog dog)//隐式转换的定义,目的在于把狗狗变成猫猫,
{
return new Cat(dog._name);
}
}
class Hashiqi:Dog
{
public Hashiqi(string name) : base(name)
{
}
new public void PrintName()
{
Console.WriteLine("二哈的名字叫 " + _name);
}
public override void Speak()
{
Console.WriteLine(_name + " is speaking" + ":wowu");
}
}
class Program
{
static void Main(string[] args)
{
Pet[] pets=new Pet[] {new Dog("Jack"),new Cat("Tom"),new Hashiqi("wangcai"),new Hashiqi("Chaijiazhe")};
for(int i=0;i<pets.Length;i++)
{
pets[i].PrintName();
pets[i].Speak();
}
Cat c = new Cat("Tom2");
ICatchMice catchM = (ICatchMice)c;//强制转换c为接口类型
c.ICatchMice();//通用接口调用
catchM.ICatchMice();//通用接口调用
IClimbTree climbT = c;//也可不用转换,本身就是一个引用类型
c.IClimbTree();
climbT.IClimbTree();
/* Dog dog = new Dog();
dog.Name = "Jack";
dog.PrintName();
Cat cat = new Cat();
cat.Name = "Tom";
cat.PrintName();
Hashiqi erha = new Hashiqi();
erha.Name = "wangcai";
erha.PrintName();*/
Dog dog0 = new Dog("tony");
Dog dog1 = new Dog("tommy");
dog0.HowToFeedDog();
dog1.HowToFeedDog();
Console.WriteLine("下面输出的是自定义转换的实例调用");
dog1.Speak();
Cat cat = dog1;
cat.Speak();
Dog.ShowNum();//静态方法调用
c.HowToFeedCat();
Console.WriteLine();
for (int j = 0; j < pets.Length; j++)
{
++pets[j];//这里的 ++ 就是重装运算符,根据定义,pet的年龄加1,返回pet,
pets[j].ShowAge();
}
}
}
}
可以隐藏实现,通过f12只能跳转到接口,看不到实现的代码
dog类之前有讲的,你可以回看一下
首先,你要清楚的是,
接口声明不包括数据成员,只能包含方法、属性、事件、索引等成员。
接口中属性声明
比如:
int x { get; set; }//声明属性存取规则
其中
get { return _x; }
set { _x=x; },在继承接口的类中实现。
###int前不能用修饰符,比如public prodected,接口默认访问级别是public .
abstract public class Pet {
protected string _name;
public Pet(string name) {
_name = name;
}
public void printName() {
Console.WriteLine("Pet name is: "+ _name);
}
// virtual public void Speak() {
// Console.WriteLine(_name + " Speak...");
// }
abstract public void Speak();
}
不同动物的cage的属性不一样,因此类的数据结构就不会一样啊,不一样的话就不能通用一个cage类,每次都需要重新写一个适用不同动物的cage类,你可以写一个cage基本类,包含了他们cage的基本共同属性,但是针对于更加细节的属性就需要继承,因此泛型就有优势了。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp8
{
public class Pet
{
public Pet(string name, uint age, string food)
{
_name = name;
_age = age;
_food = food;
}
protected string _name;
protected uint _age;
protected string _food;
protected string Voice;
virtual public void PrintName()
{
Console.WriteLine("Pet's name is" + _name);
Console.WriteLine("Pet's age is" + _age);
Console.WriteLine("Pet's favorit food is" + _food);
}
virtual public void PrintVoice()
{
Console.WriteLine("Pet's voice is spking");
}
}
public class Dog : Pet
{
public Dog(string name, uint age, string food) : base(name, age, food)
{
}
override public void PrintVoice()
{
Console.WriteLine(_name + "的叫声是:" + "汪汪汪");
}
}
public class Cat : Pet
{
public Cat(string name, uint age, string food) : base(name, age, food)
{
}
override public void PrintName()
{
Console.WriteLine("宠物的名字是:" + _name);
Console.WriteLine("宠物的年龄是" + _age);
Console.WriteLine("宠物最喜欢的食物是" + _food);
}
override public void PrintVoice()
{
Console.WriteLine(_name + "的叫声是:" + "喵喵喵");
}
}
class Program
{
static void Main(string[] args)
{
Pet[] pets = new Pet[] { new Dog("旺财", 7, "肉骨头"), new Cat("阿福", 3, "小鱼干") };
for (int i = 0; i < pets.GetLength(0); i++)
{
pets[i].PrintName();
}
for (int y = 0; y < pets.GetLength(0); y++)
{
pets[y].PrintVoice();
}
}
}
}
/*楼上说的没错,Name这个错误比明显,另外是基类里定义的食物哪里:
Console.WriteLine("Pet's favorit food is" + _age); _age换成__food,不过这表面上的东西检查完了,还有关键的是,获取数组长度哪里语法有误,改正完就ok了,更正如下:
for(int i=0; i<pets.GetLength(0); i++)
{ pets[i].PrintName(); }
for (int y = 0; y < pets.GetLength(0); y++)
{ pets[y].PrintVoice(); }
展示对接口引用作用的说明罢了
之所以会用到default关键字,是因为需要在不知道类型参数为值类型还是引用类型的情况下,为对象实例赋初值。考虑以下代码:
class TestDefault<T>
{
public T foo()
{
T t = null; //???
return t;
}
}
如果我们用int型来绑定泛型参数,那么T就是int型,那么注释的那一行就变成了 int t = null;显然这是无意义的。为了解决这一问题,引入了default关键字:
class TestDefault<T>
{
public T foo()
{
return default(T);
}
}
接口是一种规范,使得别人在实现接口的时候需要完成接口中那未实现的方法,普通类一旦实现接口就必须完成接口内所有未实现的方法,但是可以通过别的方式只去实现部分方法。
可以建一个抽象类,让抽象类去实现接口中的方法(在抽象类中,接口中的方法变成非抽象方法),最后让你那个普通类去继承抽象类,这样就可以只实现你想实现的函数方法了。(因为在普通类继承抽象类时,可以只实现抽象类中部分非抽象方法,不需要全部实现,不过抽象类中如果有抽象方法,抽象方法必须实现)
还不明白,可以百度一下
先在一个你想要注册事件类中提前写好一个委托方法,例如delegate void Handler【委托类型】();然后再写一个事件声明,例如public static event Handler【委托类型】 NewDog【事件名】;事件声明使用static,便于直接添加事件,也就是【类名.事件名 += 想要注册的方法】,取消事件是【类名.事件名 -=想要注册的方法 】
具体步骤可以这样:1.delegate void Handler【委托类型】();
2.public static event Handler【委托类型】 NewDog【事件名】;
3.【类名.事件名 += 想要注册的方法】 (这里的类名是你事件所在的那个类(也就是委托方法所在的那个类),想要注册的方法是你要给哪个类注册事件的方法)
这是我对事件的理解,如果有不对或者说的不准确的地方,希望大家能够指出,谢谢大家了,希望能帮到你,一起加油^.^
隐藏方法有它的适用场景,比如说某个父类中的方法在子类中不需要了,那么你可以直接给隐藏掉,并没有说一定要在子类中隐藏父类的方法,而是隐藏,隐藏根据实际需要,选择继承、重写或者隐藏。这就和坐公交打卡和手机支付可以同时存在,虽然你平时用不到公交卡,但是你需要用公交卡的时候你可以用。隐藏只是一种继承方式,并不是继承就必须要隐藏,希望你理解
class Pet
{
interface Iclimbtree
{
void climbtree();
}
interface Icatchmice
{
void catchmice();
}
public Pet(string name)
{
Name = name;
}
protected string Name;
virtual public void printf()
{
Console.WriteLine(Name);
}
public class Dog:Pet,Icatchmice,Iclimbtree
{
public void catchmice()
{
Console.WriteLine(" " + Name + "catch");
}
public void climbtree()
{
Console.WriteLine(" " + Name + "tree");
}
public Dog(string name):base(name)
{
}
override public void printf()
{
Console.WriteLine("mmm" + Name+"lll");
}
}
public class Cat : Pet
{
public Cat(string name):base(name)
{
}
override public void printf()
{
Console.WriteLine("mmm" + Name + "222");
}
}
}
class Program
{
static void Main(string[] args)
{
/*Pet dog1 = new Dog();
dog1.Name = "eat";
dog1.printf();
Pet cat1 = new Cat();
cat1.Name = "drink";
cat1.printf();*/
Pet[] pets = new Pet[] { new Dog("aaa"), new Cat("bbb") };
for(int i=0;i<=pets.Length;i++)
{
pets[i].printf();
}
Cat cat1 = new Cat("Tom2");
if(cat1 is Iclimbtree)
{
Iclimbtree cat = (Iclimbtree)cat1;
cat.Iclimbtree();
}
}
}
public Dog(string name).base(name)
这句话可以理解成,派生类构造函数的参数传进来,丢给base(),基类构造函数拿到这个参数,进行构造;所以不能不写
可以的,这么写应该是讲师方便复制,然后直接出结果。