如何解释对象的这种实例化? [英] How do I interpret this instantiation of an object?

查看:69
本文介绍了如何解释对象的这种实例化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是课程:



公共班鱼

{...}



公共课鲨鱼:鱼

{...}



Fish smallShark = new Shark();



我正在学习OOP。我无法解释上面发生的事情。

Here are the classes:

public class Fish
{...}

public class Shark : Fish
{...}

Fish smallShark = new Shark();

I am learning OOP.I am at a loss to explain what is going on in the above.

推荐答案

你在这里看到的是OOP概念多态性 [ ^ ]。



它基本上表示类的子类可以被视为其(或其任何)基类。在这种情况下:Shark 是一个 Fish,因此您可以将Shark的实例分配给Fish类型的变量。你也可以将它分配给Shark类型的变量,或者,如果有一个基类Animal,其中Fish将是一个子类,你也可以将它分配给Animal类型的变量。



在这个例子中,这样做的好处有点模糊。但想象一下:你有一些想和某些数据库交谈的代码。它并不关心哪种确切类型的数据库 - 它可能是SQL Server或Oracle等等。要做到这一点,它需要一个DbConnection类型的对象。由于SQL Server和Oracle的工作方式略有不同,因此与他们交谈的代码必须处理这些细节。但是,想要DbConnection对象的你的代码不处理这些细节。因此,有DbConnection的子类:SqlConnection和OracleConnection(以及其他)。这些处理相应数据库的细节。它们都是DbConnection的子类,所以你可以给你的代码SqlConnection-或OracleConnection-对象它会起作用。



(这也是设计原则的一个例子分离关注点 [ ^ ]。)
What you're "seeing" here is the OOP-concept Polymorphism[^].

It basically says that a subclass of a class can be treated as its (or any of its) baseclass(es). In this case: A Shark is a Fish, so you can assign an instance of a Shark to a variable of type Fish. You could also assign it to a variable of type Shark, or, if there was a baseclass "Animal" of which Fish would be a subclass, you could also assign it to a variable of type Animal.

The benefit of this is a bit obscure in this example. But imagine this: You have some code that "wants to talk to" some database. It doesn't care about which exact type of database - it could be SQL Server or Oracle or whatever. And to do that, it requires an object of the type "DbConnection". Because SQL Server and Oracle work a bit differently, the code "talking" to them has to deal with these specifics. But "your" code that wants the DbConnection-object doesn't deal with these specifics. For that reason there are subclasses of DbConnection: SqlConnection and OracleConnection (and others). These handle the specifics of the respective database. They both are subclasses of DbConnection, so you can "give" "your" code either a SqlConnection- or OracleConnection-object and it will work.

(This is also an example for the design principle Separation of Concerns[^].)


只是添加Sascha所说的,在现实世界中考虑一下。

你可以高兴地说这是我的车或那是你的车并参考任何制造商的例子:这是我的车如果你驾驶的车辆制造的话也一样由福特或法拉利 - 因为A Ford是汽车,就像法拉利是汽车一样。



如果你重命名你的示例:

Just to add to what Sascha says, think about it in the real world.
You can happily say "This is my Car" or "That is your Car" and refer to an example from any manufacturer: "This is my Car" works the same if the vehicle you drive is made by Ford or Ferrari - because "A Ford" is "a Car" in the same way that "A Ferrari" is "a Car".

If you rename your example slightly:
public class Car
{...}

public class Ford : Car
{...}

public class Ferrari : Car
{...}

public class Mercedes : Car
{...}


Car myCar = new Mercedes();
Car yourCar = new Ferrari();
Car joesCar = new Ford();





制作感觉?



Make sense?


这叫做降价



因为Shark继承自Fish,他们都至少有一些相同的属性。你可以使用smallShark作为鱼,并获得Shark与Fish共享的所有属性值。



这在很多方面都很方便。可能是Shark没有额外的属性但改变了Fish的一些值:



This is called down-casting

Because Shark inherits from Fish, they both have at least some of the same properties. You can use smallShark as a Fish and get all of the property values from Shark that it shares with Fish.

This can be handy in many ways. It may be that Shark has no extra properties but alters some of the values of Fish:

class Fish{
 public bool HasGills {get;set;}
 public bool IsEatenBySharks {get;set;}
 public Fish(){
  HasGills = true;
  IsEatenBySharks = true; 
 }
}
class Shark: Fish{
 Public Shark(){ //I could even call the Fish() contructor by adding ':base()' here
  HasGills = true;
  IsEatenBySharks = false; 
 }
}





这是一个非常基本的例子。



继承的另一个优点是方法覆盖:





That's a pretty basic example though.

Another advantage of inheritance is method override:

class Fish{
 public virtual Animal Describe() //the virtual keyword makes it available to be overridden
 {
   return new Animal{
     Habitat = HabitatEnum.Water,
     EyePosition = EyePosEnum.Sides,
     SkinType = SkinTypeEnum.Scales
   };
 } 
}
class Shark: Fish{
 
 public override Animal Describe(){
   //This hides the base method but the base method is still available here.
   //If I didn't override it then the original would be called instead
   Animal description = base.Describe()
   description.SkinType = SkinTypeEnum.Smooth;
   return  description;
 }

}





您通常会看到像System.Web.UI这样的东西的继承.Page或System.Web.UI.WebControls.UserControl。



这些对象的设置是为了提供使它们在Web项目中工作所需的工具,但允许你添加到他们自定义它们。



他们都有你可以覆盖的事件处理程序和你可以覆盖的方法(但在大多数情况下这有点先进。最好让他们做他们做的事情,直到你更好地理解他们。)





你可能认为这是一个'有损'的过程,但所有额外的数据仍然存在。向下投射只意味着没有已知的访问点来检索它。



举个例子:



You will commonly see inheritance for things like System.Web.UI.Page or System.Web.UI.WebControls.UserControl.

These objects are set up to provide the tools required to make them work in a web project but allow you to add to them to customize them.

They both have event handlers you can override and methods you 'can' override too (but that's a little advanced in most cases. Best to let them do what they do until you understand them better.)


You may think that this is a 'lossy' process, but all of the extra data is still there. Down-casting just means that there are no known access points to retrieve it.

Take this example:

interface IRoadVehicle{
  //Interfaces don't hold any data and cannot be instantiated.  They are just a blueprint
 int FromDealerId{get; set;} 
 int Year{get; set;} 
 string RegistrationNumber {get;set;}
 string Register(IRoadVehicle vehicle);
}
abstract class BaseRoadVehicle : IRoadVehicle{
 //This class must include the parameters from the interface
 //Abstract means that it cannot be instantiated so it must be inherited from 

 public int FromDealerId{get; set;} 
 public int Year{get; set;} 

 public string RegistrationNumber {get;set;}

 public string Register(IRoadVehicle vehicle){
   //Whatever vehicle is, we know it must have at least the IRoadVehicle parameters 
   Return RegOffice.GetNewReg(vehicle.FromDealerId, vehicle.Year)
 }
}
class MyCar : BaseRoadVehicle {
 //This class already includes everything that the BaseRoadVehicle has

 public int Wheels {get; set;}
 public int MaxPassengers {get; set;} 
 public color Color {get; set;} 

 public MyCar(){
  Wheels = 4;
  MaxPassengers = 1; //Yeah, right :Þ
  FromDealerId = 5
  Year = 2015

  RegistrationNumber = Register(this);
  //Passing this instance to the Base class does down-cast it, but it doesn't matter.
  //That method doesn't need to know the color or number of wheels.
 }
}





我可以使用反射来发现任何类型的IRoadVehicle的所有属性,但反射都发生在运行时。我无法获得预编译的代码来知道IRoadVehicle有哪些隐藏属性,除非我向上转换。

Up-Casting的最大危险在于编译器相信你知道自己该怎么做,所以你最好确保它是正确的



I could use reflection to discover all the properties of any type of IRoadVehicle, but reflection all happens at run-time. There is no way I could get the pre-compiled code to know what hidden properties IRoadVehicle has unless I up-cast.
The biggest danger of Up-Casting is that the compiler trusts that you know what your up to, so you better make sure that it's correct


这篇关于如何解释对象的这种实例化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆