В чем разница между тенью и переопределением? [Дубликат]

В дополнение к другим ответам, я рекомендую эту онлайн-службу open source jsonschema2pojo.org для быстрого генерации Java-классов из json или json-схемы для GSON, Jackson 1.x или Jackson 2.x. Например, если у вас есть:

{
   "pageInfo": {
         "pageName": "abc",
         "pagePic": "http://example.com/content.jpg"
    }
    "posts": [
         {
              "post_id": "123456789012_123456789012",
              "actor_id": 1234567890,
              "picOfPersonWhoPosted": "http://example.com/photo.jpg",
              "nameOfPersonWhoPosted": "Jane Doe",
              "message": "Sounds cool. Can't wait to see it!",
              "likesCount": 2,
              "comments": [],
              "timeOfPost": 1234567890
         }
    ]
}

jsonschema2pojo.org для генерируемого GSON:

@Generated("org.jsonschema2pojo")
public class Container {
    @SerializedName("pageInfo")
    @Expose
    public PageInfo pageInfo;
    @SerializedName("posts")
    @Expose
    public List posts = new ArrayList();
}

@Generated("org.jsonschema2pojo")
public class PageInfo {
    @SerializedName("pageName")
    @Expose
    public String pageName;
    @SerializedName("pagePic")
    @Expose
    public String pagePic;
}

@Generated("org.jsonschema2pojo")
public class Post {
    @SerializedName("post_id")
    @Expose
    public String postId;
    @SerializedName("actor_id")
    @Expose
    public long actorId;
    @SerializedName("picOfPersonWhoPosted")
    @Expose
    public String picOfPersonWhoPosted;
    @SerializedName("nameOfPersonWhoPosted")
    @Expose
    public String nameOfPersonWhoPosted;
    @SerializedName("message")
    @Expose
    public String message;
    @SerializedName("likesCount")
    @Expose
    public long likesCount;
    @SerializedName("comments")
    @Expose
    public List comments = new ArrayList();
    @SerializedName("timeOfPost")
    @Expose
    public long timeOfPost;
}

62
задан Tshepang 28 February 2014 в 10:41
поделиться

16 ответов

Я бы не считал Shadows действительно концепцией ООП. Переопределения указывают, что вы предоставляете новые или дополнительные функции для метода / свойства и т. Д., Которые были объявлены в классе предков. Тени действительно обманывают компилятор, думая, что родительский метод / свойство и т. Д. Даже не существует.

Я не использую Shadows. Придерживайтесь переопределений. Эти типы полезных «особенностей», которые VB обеспечивал годами, в конечном итоге приводят к горю в какой-то момент.

-12
ответ дан Jim Petkus 28 August 2018 в 01:26
поделиться

Ну вот ответ по коду.

Module Module1

    Sub Main()
        Dim object1 As Parent = New Child()
        Console.WriteLine("object1, reference type Parent and object type Child")
        object1.TryMe1()
        object1.TryMe2()
        object1.TryMe3()

        Console.WriteLine("")
        Console.WriteLine("")
        Console.WriteLine("object2, reference type Child and object type Child")
        Dim object2 As Child = New Child()

        object2.TryMe1()
        object2.TryMe2()
        object2.TryMe3()

        Console.ReadLine()
    End Sub

End Module

Public Class Parent

    Public Sub TryMe1()
        Console.WriteLine("Testing Shadow: Parent.WriteMe1")
    End Sub

    Public Overridable Sub TryMe2()
        Console.WriteLine("Testing override: Parent.WriteMe2")
    End Sub

    Public Sub TryMe3()
        Console.WriteLine("Testing Shadow without explicitly writing shadow modifier: Parent.WriteMe3")
    End Sub
End Class

Public Class Child
    Inherits Parent

    Public Shadows Sub TryMe1()
        Console.WriteLine("Testing Shadow: Child.WriteMe1")
    End Sub

    Public Overrides Sub TryMe2()
        Console.WriteLine("Testing override: Child.WriteMe2")
    End Sub

    Public Sub TryMe3()
    Console.WriteLine("Testing Shadow without explicitly writing shadow modifier: Child.WriteMe3")
    End Sub
End Class


'Output:
'object1, reference type Parent and object type Child
'Testing Shadow: Parent.WriteMe1
'Testing override: Child.WriteMe2
'Testing Shadow without explicitly writing shadow modifier: Parent.WriteMe3


'object2, reference type Child and object type Child
'Testing Shadow: Child.WriteMe1
'Testing override: Child.WriteMe2
'Testing Shadow without explicitly writing shadow modifier: Child.WriteMe3

Вы можете скопировать его и попробовать сами. Поскольку вы видите, что затенение является поведением по умолчанию, а Visual Studio предупреждает вас, когда выполняется теневое копирование без явного написания модификатора тени.

Примечание. Для меня я никогда не использовал ссылку на базовый класс к дочернему объекту. Для таких случаев я всегда использую интерфейсы.

1
ответ дан A Khudairy 28 August 2018 в 01:26
поделиться

Я согласен с Джимом. Я никогда не нашел законного использования для Shadows. Обычно, если я это вижу, я предполагаю, что часть раздела кода должна быть реорганизована бит.

Я полагаю, что она существует, чтобы вы могли затенять метод из сборки, в которой у вас нет контроль над исходным кодом. В этом случае рефакторинг родительского класса будет невозможным.

0
ответ дан Chad Braun-Duin 28 August 2018 в 01:26
поделиться

Это недавняя ссылка MSDN: Различия между затенением и переопределением

Shadowing защищает от последующей модификации базового класса, которая вводит член, который вы уже определили в ваш производный класс. Обычно вы используете затенение в следующих случаях:

** Вы ожидаете, что ваш базовый класс может быть изменен, чтобы определить элемент с тем же именем, что и ваш. *

** Вы хотите свободу изменения типа элемента или последовательности вызовов. *

(я еще не исследовал использование в отношении области и типов)

2
ответ дан CMH 28 August 2018 в 01:26
поделиться

Тенерирование, вероятно, не делает того, что вы думаете.

Рассмотрим следующие классы:

Public MustInherit Class A 
    Public Function fX() As Integer
        Return 0
    End Function
End Class

Public Class B
    Inherits A 
    Public Shadows Function fX() As Integer
        Return 1
    End Function 
End Class

Теперь я использую их:

Dim oA As A
Dim oB As New B
oA = oB

Вероятно, вы думаете, что oA и oB имеют одинаковое право?

Нет.

oA.fx = 0, в то время как oB.fx = 1

Imho это очень опасное поведение, и это почти не упоминается в документах.

Если вы использовали они будут одинаковыми.

Таким образом, хотя есть законные способы использования теней, вероятность того, что вы делаете, не является одним из них, и этого следует избегать.

18
ответ дан dwidel 28 August 2018 в 01:26
поделиться

Я думаю, что есть действительно два сценария, которые люди принимают здесь, и оба являются законными. Вы действительно можете разбить их на дизайнера базового класса и спустя годы разработчика, который реализует подкласс, который не может изменить базовый класс. Так что да, лучше всего переодеться, если у вас есть эта роскошь. Это чистый подход OOD.

С другой стороны, у вас может быть что-то вроде примера, приведенного выше, где вы находитесь на другом конце этого уравнения, чтобы реализовать подкласс, и вы не можете изменить тот факт, что метод, который вам нужно переопределить, не помечены как надменные. Возьмем, к примеру,

Public Shadows Function Focus() As Boolean
    txtSearch.Focus()
    Return MyBase.Focus()
End Function

. В этом случае я наследую свой класс из класса управления Winform, который, к сожалению, не отмечен как переопределяемый. На этом этапе я столкнулся с тем, что просто сделал код «чистым» или упростил его понимание. Клиент этого элемента управления просто хочет вызвать control.Focus () и, вероятно, все равно. Я мог бы назвать этот метод FocusSearchText () или Focus2 и т. Д., Но я считаю, что выше код намного проще для клиентского кода. Это правда, что если клиент затем переводит этот элемент управления в качестве базового класса и вызывает фокус, мой код не будет вызывать. Но это довольно отдаленно.

В конце концов, это сводится к решению суда, и вы должны будете сделать.

4
ответ дан ebol2000 28 August 2018 в 01:26
поделиться

Shadow позволяет выполнять определенные действия, которые невозможно выполнить с переопределениями.

В моем собственном случае: у меня есть несколько классов таблиц с общей функциональностью; но для кого сами коллекции имеют разные типы.

Public Class GenericTable
Protected Friend Overridable Property Contents As System.Collections.Generic.List(Of GenericItem)
    ... do stuff ...
End Class

Тогда у меня есть конкретные isntances:

Public Class WidgetTable
Inherits GenericTable
Protected Friend Shadows Property Contents As System.Collections.Generic.List(Of Widget)
    ... stuff is inhereted ...
End Class

Я не мог переопределить, потому что тип был изменен.

2
ответ дан Jerry 28 August 2018 в 01:26
поделиться

Я нашел другое различие. См. Это:

Sub Main()
    Dim X As New Derived
    Dim Y As Base = New Derived
    Console.WriteLine("X:" & X.Test())
    Console.WriteLine("Y:" & Y.Test())
    Console.WriteLine("X:" & CType(X, Base).Test)
    Console.WriteLine("X:" & X.Func())
    Console.WriteLine("Y:" & Y.Func())
    Console.WriteLine("X:" & CType(X, Base).Func)
    Console.ReadKey()
End Sub
Public Class Base
    Public Overridable Function Func() As String
        Return "Standard"
    End Function
    Function Test() As String
        Return Me.Func()
    End Function
End Class
Public Class Derived
    Inherits Base
    Public $$$ Function Func() As String
        Return "Passed By Class1" & " - " & MyBase.Func
    End Function
End Class

Если вы используете Overrides (где есть $$$), то нет возможности использовать класс Func on Base, если определение экземпляра Derived и если определение является базой, но экземпляр имеет тип Derived.

Если вы используете Shadows, единственный способ увидеть Func в производном классе - определить экземпляр как Derived и не перейти к метод базового класса (X.Test возвращает стандарт). Я думаю, что это главное: если я использую Shadows, метод не будет перегружать базовый метод внутри базовых методов.

Это подход OOP Overloads. Если я получаю класс и НЕ НУЖНО, я хочу, чтобы метод вызывался, я должен использовать Overloads. Для экземпляров моих объектов нет способа вернуть «Стандарт» (за исключением использования отражений, я думаю). Я думаю, что intellisense немного путается. Если я выделил Y.Func, будет выделен Func в базовый класс, но будет выполнен Func в производный класс.

С помощью Shadows новый метод доступен только напрямую. Как и Overloads, но скрывая перегрузки базового класса (я думаю, что это ошибка, возвращаемая перед компиляцией, потому что вы можете вызвать ее с помощью трансляции, например, неявной, сделанной с использованием перегрузки).

2
ответ дан Lucio Menci 28 August 2018 в 01:26
поделиться

Переопределения - более нормальный квалификатор. Если дочерний класс переопределяет функцию базового класса таким образом, то независимо от того, как ссылается дочерний объект (с использованием базового класса или ссылки на дочерний класс), вызывается дочерняя функция.

С другой стороны, если функция дочернего класса Shadows выполняет функцию базового класса, тогда дочерний объект, к которому обращаются через ссылку базового класса, будет использовать эту функцию базового класса, несмотря на то, что это дочерний объект. Определение дочерней функции используется только при обращении к дочернему объекту с использованием соответствующей дочерней ссылки.

85
ответ дан Nick 28 August 2018 в 01:26
поделиться

Пример затенения: предположим, что вы хотите использовать функцию в стороннем компоненте, но функция защищена. Вы можете обойти это ограничение простым наследованием и выставить затененную функцию, которая в основном вызывает его базовую функцию:

Public Class Base

    Protected Sub Configure()
        ....
    End Sub

End Class

Public Class Inherited
    Inherits Base

    Public Shadows Sub Configure()
        MyBase.Configure()
    End Sub

End Class
6
ответ дан Peter Mortensen 28 August 2018 в 01:26
поделиться

Использование теней редко, но верно. Кроме того, вы не можете переопределить общий (статический) метод. Поэтому вы должны затенять общий метод, если хотите «переопределить» его.

0
ответ дан Piero 28 August 2018 в 01:26
поделиться

Тени могут быть очень полезными, если вы пишете обертку вокруг существующего элемента управления.

Например, рядом со списком. Затеняя AutoCompleteSource, вы можете помешать ему установить незаконное значение для вашего специального вида combobox, даже когда оно будет передано в обычное поле со списком. Или выполните предварительную обработку, прежде чем использовать mybase.AutoCompleteSource = value в свойстве shadowing.

0
ответ дан Quanlong 28 August 2018 в 01:26
поделиться

Я хотел использовать System.Web.HttpContext.Current.Response вместо Response.redirect и нуждался в удобстве для кода как Response.redirect. Я определил свойство readonly с именем Response, чтобы затенять оригинал в базовом классе. Я не мог использовать переопределения, поскольку это свойство не является переопределяемым. Очень удобно:)

0
ответ дан Siddharth Rout 28 August 2018 в 01:26
поделиться

Ключевое слово «тени» по существу говорит: «Если кто-либо, кто обращается к этому объекту, знает, что он имеет этот тип или один из его потомков, используйте этот элемент, иначе используйте базовый». Простейшим примером этого может быть базовый класс ThingFactory, который включает в себя метод «MakeNew», который возвращает Thing, и класс CarFactory, полученный от ThingFactory, метод «MakeNew» всегда возвращает Вещь, которая будет иметь производный тип Car. Если рутина знает, что ThingFactory, с которым он держится, происходит, в частности, CarFactory, тогда он будет использовать затененный CarFactory.MakeNew (если таковой существует), который может указывать тип возврата в качестве автомобиля. Если рутина не знает, что его ThingFactory на самом деле является CarFactory, он будет использовать не скрытый MakeNew (который должен вызывать внутренний защищенный переопределяемый метод MakeDerivedThing).

Кстати, другое хорошее использование теней для предотвращения доступа к производным классам защищенных методов, которые больше не будут работать. Невозможно просто скрыть член от производных классов, отличных от назначения нового, но можно запретить производным классам что-либо делать с защищенным членом, объявив новый защищенный пустой класс с этим именем. Например, если вызов объекта MemberwiseClone на объекте сломает его, можно объявить:

  Protected Shadows Class MemberwiseClone
  End Class
Обратите внимание, что это не нарушает принципы ООП, такие как Принцип замещения Лискова, поскольку это применимо только в случаях, когда производный класс может использоваться вместо объект базового класса. Если Foo и Bar наследуются от Boz, метод, который принимает параметр Boz, может быть законно передан в Foo или Bar вместо этого. С другой стороны, объект типа Foo будет знать, что его объект базового класса имеет тип Boz. Это никогда не будет чем-то другим (например, он не будет баром).

6
ответ дан supercat 28 August 2018 в 01:26
поделиться

Иногда небольшой пример действительно помогает понять разницу техническим способом.

Sub Main()

    Dim o As New ChildClass

    Console.WriteLine(o.GetValOverride()) ' Prints 2
    Console.WriteLine(o.GetValShadow()) ' Prints 2
    Console.WriteLine(CType(o, ParentClass).GetValOverride()) ' Prints 2
    Console.WriteLine(CType(o, ParentClass).GetValShadow()) ' Prints 1
    Console.ReadLine()

End Sub

Class ParentClass

    Public Overridable Function GetValOverride() As String
        Return "1"
    End Function

    Public Function GetValShadow() As String
        Return "1"
    End Function

End Class

Class ChildClass
    Inherits ParentClass

    Public Overrides Function GetValOverride() As String
        Return "2"
    End Function

    Public Shadows Function GetValShadow() As String
        Return "2"
    End Function

End Class
9
ответ дан the_lotus 28 August 2018 в 01:26
поделиться

Переопределения - расширение или создание альтернативных функций для метода.

Пример: добавление или расширение функциональности события Paint в окне.


    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e) ' retain the base class functionality
        'add code for extended functionality here
    End Sub

Тени - переопределяет унаследованный метод и заставляет его использовать для всех классов, созданных с этим типом. Другими словами, метод не перегружен, но переопределен и методы базового класса недоступны, что заставляет использовать функцию, объявленную в классе. Тени сохраняют или сохраняют определение метода таким образом, что оно не уничтожается, если методы базового класса модифицированы.

Пример: принудительно использовать все классы «B» для использования его oddball. Добавьте определение, которое, если A class Add методы изменены, это не повлияет на добавление B. (Скрывает все методы «Добавить» базового класса. Не сможет вызвать A.Add (x, y, z) из экземпляра B.)


    Public Class A
        Public Function Add(ByVal x As Integer, ByVal y As Integer) As Integer
            Return x + y
        End Function
        Public Function Add(ByVal x As Integer, ByVal y As Integer, ByVal z As Integer) As Integer
            Return x + y + z
        End Function
    End Class
    Public Class B
        Inherits A
        Public Shadows Function Add(ByVal x As Integer, ByVal y As Integer) As Integer
            Return x - y
        End Function
    End Class
14
ответ дан user50612 28 August 2018 в 01:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: